[libc] add n versions of sprintf and vprintf
diff --git a/include/printf.h b/include/printf.h
index 5006530..2d09120 100644
--- a/include/printf.h
+++ b/include/printf.h
@@ -33,7 +33,9 @@
int printf(const char *fmt, ...);
int sprintf(char *str, const char *fmt, ...) __PRINTFLIKE(2, 3);
+int snprintf(char *str, size_t len, const char *fmt, ...) __PRINTFLIKE(3, 4);
int vsprintf(char *str, const char *fmt, va_list ap);
+int vsnprintf(char *str, size_t len, const char *fmt, va_list ap);
#if defined(__cplusplus)
}
diff --git a/lib/libc/printf.c b/lib/libc/printf.c
index af9379e..b7bf2bb 100644
--- a/lib/libc/printf.c
+++ b/lib/libc/printf.c
@@ -66,6 +66,18 @@
return err;
}
+int snprintf(char *str, size_t len, const char *fmt, ...)
+{
+ int err;
+
+ va_list ap;
+ va_start(ap, fmt);
+ err = vsnprintf(str, len, fmt, ap);
+ va_end(ap);
+
+ return err;
+}
+
#define LONGFLAG 0x00000001
#define LONGLONGFLAG 0x00000002
@@ -134,6 +146,11 @@
int vsprintf(char *str, const char *fmt, va_list ap)
{
+ return vsnprintf(str, INT_MAX, fmt, ap);
+}
+
+int vsnprintf(char *str, size_t len, const char *fmt, va_list ap)
+{
char c;
unsigned char uc;
const char *s;
@@ -141,10 +158,11 @@
void *ptr;
int flags;
unsigned int format_num;
- int chars_written = 0;
+ size_t chars_written = 0;
char num_buffer[32];
-#define OUTPUT_CHAR(c) do { (*str++ = c); chars_written++; } while(0)
+#define OUTPUT_CHAR(c) do { (*str++ = c); chars_written++; if (chars_written + 1 == len) goto done; } while(0)
+#define OUTPUT_CHAR_NOLENCHECK(c) do { (*str++ = c); chars_written++; } while(0)
for(;;) {
/* handle regular chars that aren't format related */
@@ -309,11 +327,13 @@
continue;
}
+done:
/* null terminate */
- OUTPUT_CHAR('\0');
+ OUTPUT_CHAR_NOLENCHECK('\0');
chars_written--; /* don't count the null */
#undef OUTPUT_CHAR
+#undef OUTPUT_CHAR_NOLENCHECK
return chars_written;
}