summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2014-05-30 09:43:32 +0000
committerhselasky <hselasky@FreeBSD.org>2014-05-30 09:43:32 +0000
commit6b258c1f8041dabc6c5e1a8a940efe3c54c115a3 (patch)
tree96c706928349261fc593b8db8d4351c74afe8344
parent999343aa9c8c5d59dd1019605c99cfacb2840d77 (diff)
downloadFreeBSD-src-6b258c1f8041dabc6c5e1a8a940efe3c54c115a3.zip
FreeBSD-src-6b258c1f8041dabc6c5e1a8a940efe3c54c115a3.tar.gz
Add support for snprintf() to libstand.
Reviewed by: brooks @ Sponsored by: DARPA, AFRL
-rw-r--r--lib/libstand/printf.c59
-rw-r--r--lib/libstand/stand.h1
2 files changed, 54 insertions, 6 deletions
diff --git a/lib/libstand/printf.c b/lib/libstand/printf.c
index 977c026..1a86e93 100644
--- a/lib/libstand/printf.c
+++ b/lib/libstand/printf.c
@@ -56,8 +56,16 @@ __FBSDID("$FreeBSD$");
#define MAXNBUF (sizeof(intmax_t) * CHAR_BIT + 1)
+typedef void (kvprintf_fn_t)(int, void *);
+
static char *ksprintn (char *buf, uintmax_t num, int base, int *len, int upper);
-static int kvprintf(char const *fmt, void (*func)(int), void *arg, int radix, va_list ap);
+static int kvprintf(char const *fmt, kvprintf_fn_t *func, void *arg, int radix, va_list ap);
+
+static void
+putchar_wrapper(int cc, void *arg)
+{
+ putchar(cc);
+}
int
printf(const char *fmt, ...)
@@ -66,7 +74,7 @@ printf(const char *fmt, ...)
int retval;
va_start(ap, fmt);
- retval = kvprintf(fmt, putchar, NULL, 10, ap);
+ retval = kvprintf(fmt, putchar_wrapper, NULL, 10, ap);
va_end(ap);
return retval;
}
@@ -74,8 +82,7 @@ printf(const char *fmt, ...)
void
vprintf(const char *fmt, va_list ap)
{
-
- kvprintf(fmt, putchar, NULL, 10, ap);
+ kvprintf(fmt, putchar_wrapper, NULL, 10, ap);
}
int
@@ -91,6 +98,46 @@ sprintf(char *buf, const char *cfmt, ...)
return retval;
}
+struct print_buf {
+ char *buf;
+ size_t size;
+};
+
+static void
+snprint_func(int ch, void *arg)
+{
+ struct print_buf *pbuf = arg;
+
+ if (pbuf->size < 2) {
+ /*
+ * Reserve last buffer position for the terminating
+ * character:
+ */
+ return;
+ }
+ *(pbuf->buf)++ = ch;
+ pbuf->size--;
+}
+
+int
+snprintf(char *buf, size_t size, const char *cfmt, ...)
+{
+ int retval;
+ va_list ap;
+ struct print_buf arg;
+
+ arg.buf = buf;
+ arg.size = size;
+
+ va_start(ap, cfmt);
+ retval = kvprintf(cfmt, &snprint_func, &arg, 10, ap);
+ va_end(ap);
+
+ if (arg.size >= 1)
+ *(arg.buf)++ = 0;
+ return retval;
+}
+
void
vsprintf(char *buf, const char *cfmt, va_list ap)
{
@@ -149,9 +196,9 @@ ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
* ("%*D", len, ptr, " " -> XX XX XX XX ...
*/
static int
-kvprintf(char const *fmt, void (*func)(int), void *arg, int radix, va_list ap)
+kvprintf(char const *fmt, kvprintf_fn_t *func, void *arg, int radix, va_list ap)
{
-#define PCHAR(c) {int cc=(c); if (func) (*func)(cc); else *d++ = cc; retval++; }
+#define PCHAR(c) {int cc=(c); if (func) (*func)(cc, arg); else *d++ = cc; retval++; }
char nbuf[MAXNBUF];
char *d;
const char *p, *percent, *q;
diff --git a/lib/libstand/stand.h b/lib/libstand/stand.h
index 2a1e9a9..2808722 100644
--- a/lib/libstand/stand.h
+++ b/lib/libstand/stand.h
@@ -238,6 +238,7 @@ extern void mallocstats(void);
extern int printf(const char *fmt, ...) __printflike(1, 2);
extern void vprintf(const char *fmt, __va_list);
extern int sprintf(char *buf, const char *cfmt, ...) __printflike(2, 3);
+extern int snprintf(char *buf, size_t size, const char *cfmt, ...) __printflike(3, 4);
extern void vsprintf(char *buf, const char *cfmt, __va_list);
extern void twiddle(void);
OpenPOWER on IntegriCloud