summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorian <ian@FreeBSD.org>2014-10-26 02:51:56 +0000
committerian <ian@FreeBSD.org>2014-10-26 02:51:56 +0000
commit1edaa04098842aaa04cd15d9c29a0668cd5ed91f (patch)
treebe306da713e176ccfd86f25970825e45dbc725d4 /lib
parent6bda1023a0b349e5b577181f03fb93e6d8744f69 (diff)
downloadFreeBSD-src-1edaa04098842aaa04cd15d9c29a0668cd5ed91f.zip
FreeBSD-src-1edaa04098842aaa04cd15d9c29a0668cd5ed91f.tar.gz
MFC r266878, r266879: Add support for snprintf() to libstand.
Diffstat (limited to 'lib')
-rw-r--r--lib/libstand/printf.c59
-rw-r--r--lib/libstand/stand.h1
2 files changed, 55 insertions, 5 deletions
diff --git a/lib/libstand/printf.c b/lib/libstand/printf.c
index 977c026..157b327 100644
--- a/lib/libstand/printf.c
+++ b/lib/libstand/printf.c
@@ -56,8 +56,17 @@ __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 +75,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;
}
@@ -75,7 +84,7 @@ void
vprintf(const char *fmt, va_list ap)
{
- kvprintf(fmt, putchar, NULL, 10, ap);
+ kvprintf(fmt, putchar_wrapper, NULL, 10, ap);
}
int
@@ -91,6 +100,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 +198,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