mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Nick Andrew <nick@nick-andrew.net>
To: Andrew Morton <akpm@linux-foundation.org>,
	Linus Torvalds <torvalds@linux-foundation.org>
Cc: <linux-kernel@vger.kernel.org>
Subject: [RFC PATCH v1 1/3] Split the vsnprintf function into two parts
Date: Sat, 06 Dec 2008 17:59:43 +1100	[thread overview]
Message-ID: <20081206065943.29149.15870.stgit@marcab.local.tull.net> (raw)
In-Reply-To: <20081206065922.29149.63380.stgit@marcab.local.tull.net>

Split the vsnprintf function into two parts

Two functions are required for recursion because we want the
recursive part to be able to run (and calcalate the output
size) even beyond its buffer size.

Signed-off-by: Nick Andrew <nick@nick-andrew.net>
---

 lib/vsprintf.c |  100 ++++++++++++++++++++++++++++++++++++--------------------
 1 files changed, 65 insertions(+), 35 deletions(-)


diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index a013bbc..1e2dcaf 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -616,10 +616,15 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field
 	return number(buf, end, (unsigned long) ptr, 16, field_width, precision, flags);
 }
 
-/**
- * vsnprintf - Format a string and place it in a buffer
- * @buf: The buffer to place the result into
- * @size: The size of the buffer, including the trailing null space
+/*
+ * __vsnprintfr: Recursive implementation of vsnprintf.
+ *
+ * See the description for vsnprintf, which calls __vsnprintfr.
+ * __vsnprintfr can call itself recursively.
+ *
+ * @buf: The start address of the output buffer
+ * @str: The current write position (may extend beyond the buffer)
+ * @end: One address past the end of the buffer
  * @fmt: The format string to use
  * @args: Arguments for the format string
  *
@@ -628,22 +633,14 @@ static char *pointer(const char *fmt, char *buf, char *end, void *ptr, int field
  * %pF output the name of a function pointer
  * %pR output the address range in a struct resource
  *
- * The return value is the number of characters which would
- * be generated for the given input, excluding the trailing
- * '\0', as per ISO C99. If you want to have the exact
- * number of characters written into @buf as return value
- * (not including the trailing '\0'), use vscnprintf(). If the
- * return is greater than or equal to @size, the resulting
- * string is truncated.
- *
- * Call this function if you are already dealing with a va_list.
- * You probably want snprintf() instead.
  */
-int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
+
+static char *__vsnprintfr(char *buf, char *str, char *end,
+			const char *fmt, va_list args)
 {
 	unsigned long long num;
 	int base;
-	char *str, *end, c;
+	char c;
 
 	int flags;		/* flags to number() */
 
@@ -655,25 +652,6 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
 				/* 'z' changed to 'Z' --davidm 1/25/99 */
 				/* 't' added for ptrdiff_t */
 
-	/* Reject out-of-range values early.  Large positive sizes are
-	   used for unknown buffer sizes. */
-	if (unlikely((int) size < 0)) {
-		/* There can be only one.. */
-		static char warn = 1;
-		WARN_ON(warn);
-		warn = 0;
-		return 0;
-	}
-
-	str = buf;
-	end = buf + size;
-
-	/* Make sure end is always >= buf */
-	if (end < buf) {
-		end = ((void *)-1);
-		size = end - buf;
-	}
-
 	for (; *fmt ; ++fmt) {
 		if (*fmt != '%') {
 			if (str < end)
@@ -844,12 +822,64 @@ int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
 		str = number(str, end, num, base,
 				field_width, precision, flags);
 	}
+
+	return str;
+}
+
+/**
+ * vsnprintf - Format a string and place it in a buffer
+ * @buf: The buffer to place the result into
+ * @size: The size of the buffer, including the trailing null space
+ * @fmt: The format string to use
+ * @args: Arguments for the format string
+ *
+ * Also see __vsnprintfr above.
+ *
+ * The return value is the number of characters which would
+ * be generated for the given input, excluding the trailing
+ * '\0', as per ISO C99. If you want to have the exact
+ * number of characters written into @buf as return value
+ * (not including the trailing '\0'), use vscnprintf(). If the
+ * return is greater than or equal to @size, the resulting
+ * string is truncated.
+ *
+ * Call this function if you are already dealing with a va_list.
+ * You probably want snprintf() instead.
+ */
+
+int vsnprintf(char *buf, size_t size, const char *fmt, va_list args)
+{
+	char *str, *end;
+
+	/* Reject out-of-range values early.  Large positive sizes are
+	 * used for unknown buffer sizes.
+	 */
+	if (unlikely((int) size < 0)) {
+		/* There can be only one.. */
+		static char warn = 1;
+		WARN_ON(warn);
+		warn = 0;
+		return 0;
+	}
+
+	end = buf + size;
+
+	/* Make sure end is always >= buf */
+	if (end < buf) {
+		end = ((void *)-1);
+		size = end - buf;
+	}
+
+	/* format the args, writing them between 'buf' and 'end' */
+	str = __vsnprintfr(buf, buf, end, fmt, args);
+
 	if (size > 0) {
 		if (str < end)
 			*str = '\0';
 		else
 			end[-1] = '\0';
 	}
+
 	/* the trailing null byte doesn't count towards the total */
 	return str-buf;
 }


  reply	other threads:[~2008-12-06  6:59 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-12-06  6:59 [RFC] Recursive printk Nick Andrew
2008-12-06  6:59 ` Nick Andrew [this message]
2008-12-06  7:00 ` [RFC PATCH v1 2/3] Add %v support to vsnprintf() Nick Andrew
2008-12-06 17:27   ` Linus Torvalds
2008-12-06  7:00 ` [RFC PATCH v1 3/3] Sample refactor of socket.c to use recursive printk Nick Andrew
2008-12-06  7:03   ` David Miller
2008-12-06  7:18   ` Valdis.Kletnieks
2008-12-06  7:40     ` Nick Andrew
2008-12-06  7:20 ` [RFC] Recursive printk Andrew Morton
2008-12-06  7:33   ` Willy Tarreau
2008-12-06  7:41     ` Andrew Morton
2008-12-06  8:16       ` Willy Tarreau
2008-12-06  9:43       ` Takashi Iwai
2008-12-06  7:42   ` Joe Perches
2008-12-06  8:40     ` Nick Andrew
2008-12-06  9:11       ` Joe Perches
2008-12-06 23:16         ` Nick Andrew
2008-12-06 23:24           ` Linus Torvalds
2008-12-06 19:35       ` Al Viro
2008-12-06  8:30   ` Nick Andrew
2008-12-08  1:42     ` Tejun Heo

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20081206065943.29149.15870.stgit@marcab.local.tull.net \
    --to=nick@nick-andrew.net \
    --cc=akpm@linux-foundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=torvalds@linux-foundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome