ref: 54374eb1baef2600d9fd2aabd08f71a16d50a392
parent: 7599d1a808bd0b604b7e5cde5a84342cf868509e
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Sat Mar 4 02:19:52 EST 2017
[libc] Add skeleton of vfprintf() This is a first version of a minimal vfprintf. This version only supports %d, %c, %o, %x and %s that is good enough to help us to debug other routines.
--- a/libc/src/Makefile
+++ b/libc/src/Makefile
@@ -10,7 +10,8 @@
isalnum.o isalpha.o isascii.o isblank.o iscntrl.o isdigit.o \
isgraph.o islower.o isprint.o ispunct.o isspace.o isupper.o \
isxdigit.o toupper.o tolower.o ctype.o setlocale.o \
- localeconv.o atoi.o atexit.o exit.o
+ localeconv.o atoi.o atexit.o exit.o \
+ printf.o fprintf.o vfprintf.o
all: libc.a
--- /dev/null
+++ b/libc/src/fprintf.c
@@ -1,0 +1,17 @@
+/* See LICENSE file for copyright and license details. */
+
+#include <stdarg.h>
+#include <stdio.h>
+#undef fprintf
+
+int
+fprintf(FILE * restrict fp, const char * restrict fmt, ...)
+{
+ va_list va;
+ int cnt;
+
+ va_start(va, fmt);
+ cnt = vfprintf(fp, fmt, va);
+ va_end(va);
+ return cnt;
+}
--- /dev/null
+++ b/libc/src/printf.c
@@ -1,0 +1,17 @@
+/* See LICENSE file for copyright and license details. */
+
+#include <stdarg.h>
+#include <stdio.h>
+#undef printf
+
+int
+printf(const char * restrict fmt, ...)
+{
+ int cnt;
+ va_list va;
+
+ va_start(va, fmt);
+ cnt = vfprintf(stdin, fmt, va);
+ va_end(va);
+ return cnt;
+}
--- /dev/null
+++ b/libc/src/vfprintf.c
@@ -1,0 +1,76 @@
+/* See LICENSE file for copyright and license details. */
+
+#include <stdarg.h>
+#include <stdio.h>
+#undef vfprintf
+
+static int
+printn2(FILE * restrict fp, unsigned n, int base)
+{
+ unsigned t;
+ int cnt = 0;
+ static char digits[] = "0123456789ABCDEF";
+
+ if ((t = n / base) != 0)
+ cnt += printn2(fp, t, base);
+ putc(digits[n % base], fp);
+ return cnt + 1;
+}
+
+static int
+printn(FILE * restrict fp, int n, int b, int sign)
+{
+ int cnt = 0;
+
+ if (sign && n < 0) {
+ n = -n;
+ putc('-', fp);
+ ++cnt;
+ }
+ cnt += printn2(fp, n, b);
+ return cnt;
+}
+
+int
+vfprintf(FILE * restrict fp, const char *fmt, va_list va)
+{
+ int c, base, sign, cnt;
+ char *s;
+
+ while (( c = *fmt++) != '\0') {
+ if (c == '%') {
+ sign = 0;
+ switch (*fmt++) {
+ case '%':
+ c = '%';
+ break;
+ case 'c':
+ c = va_arg(va, int);
+ break;
+ case 'o':
+ base = 8;
+ goto numeric;
+ case 'd':
+ sign = 1;
+ base = 10;
+ goto numeric;
+ case 'x':
+ base = 16;
+ numeric:
+ c = va_arg(va, int);
+ cnt += printn(fp, c, base, sign);
+ continue;
+ case 's':
+ s = va_arg(va, char *);
+ while ((c = *s++) != '\0')
+ putc(c, fp);
+ /* passthrou */
+ default:
+ continue;
+ }
+ }
+ putc(c, fp);
+ ++cnt;
+ }
+ return cnt;
+}