commit 53c6ad2c93c5468c14cf32746b5860d30bad86d2
parent 6ed9f65751c404328c6c2e52d599397ef988d3d7
Author: Roberto Vargas <roberto.vargas@arm.com>
Date: Tue, 13 Nov 2018 10:34:54 +0000
[libk] Add ksnprint()
Change-Id: Ie4f29793cbb5fd55056be00139dae4fcc26a1886
Diffstat:
9 files changed, 192 insertions(+), 132 deletions(-)
diff --git a/include/rcode.h b/include/rcode.h
@@ -3,9 +3,11 @@
#include <stdint.h>
#if __GNUC__ || __clang__
-#define PRINTKFMT __attribute__ ((format (printf, 1, 2)))
+#define KPRINTFMT __attribute__ ((format (printf, 1, 2)))
+#define KSNPRINTFMT __attribute__ ((format (printf, 3, 4)))
#else
-#define PRINTKFMT
+#define KPRINTFMT
+#define KSNPRINTFMT
#endif
#if __STDC_VERSION__ >= 201112L
@@ -16,9 +18,9 @@
#endif
#ifndef NDEBUG
-#define dbg printk
+#define dbg kprint
#else
-#define dbg(fmt, ...)
+#define dbg
#endif
#define PAGESIZE 4096
@@ -137,8 +139,9 @@ extern void rmc(Rmucmd *cmd);
extern int debug(void);
/* libk */
-extern void printk(const char * restrict fmt, ...) PRINTKFMT;
extern struct bssmap *bss(void);
+extern int kprint(const char *fmt, ...) KPRINTFMT;
+extern int ksnprint(char *str, size_t len, const char *fmt, ...) KSNPRINTFMT;
extern char *kgetln(char *s, int n);
extern int kgetc(void);
diff --git a/src/libk/Makefile b/src/libk/Makefile
@@ -2,8 +2,10 @@
PROJECTDIR=../..
include $(PROJECTDIR)/scripts/rules.mk
-OBJS = printk.o \
- bss-$(SYS).o \
+OBJS = bss-$(SYS).o \
+ doprnt.o \
+ kprint.o \
+ ksnprint.o \
kgetc-$(SYS).o \
kgetln.o \
__assert.o \
diff --git a/src/libk/__assert.c b/src/libk/__assert.c
@@ -5,6 +5,6 @@ extern void printk(const char * restrict fmt, ...);
void __assert(char *exp, char *file, long line)
{
- printk("%s:%ld: assertion failed '%s'\n", file, line, exp);
+ kprint("%s:%ld: assertion failed '%s'\n", file, line, exp);
abort();
}
diff --git a/src/libk/doprnt.c b/src/libk/doprnt.c
@@ -0,0 +1,126 @@
+#include <stdarg.h>
+#include <stddef.h>
+
+#include "libk.h"
+#include "../libc/syscall.h"
+
+static void
+putch(Stream *sp, int c)
+{
+ char ch;
+
+ if (sp->fd < 0) {
+ if (sp->cnt < sp->len)
+ sp->base[sp->cnt++] = c;
+ } else {
+ ch = c;
+ _write(sp->fd, &ch, 1);
+ sp->cnt++;
+ }
+}
+
+static void
+printn(Stream *sp, long long n, int base, int sign)
+{
+ int first, d;
+ unsigned long long div;
+ const static char digits[] = "0123456789ABCDEF";
+
+ switch (base) {
+ case 8:
+ div = 01000000000000000000000u;
+ break;
+ case 10:
+ div = 10000000000000000000u;
+ break;
+ case 16:
+ div = 0x1000000000000000u;
+ break;
+ }
+
+ if (sign && n < 0) {
+ n = -n;
+ putch(sp, '-');
+ }
+
+ for (first = 1; div > 0; div /= base) {
+ d = n / div;
+ if (d == 0 && first && div != 1)
+ continue;
+ n -= d * div;
+ putch(sp, digits[d]);
+ first = 0;
+ }
+}
+
+static long long
+getnum(va_list *va, int size)
+{
+ switch (size) {
+ case 0:
+ return va_arg(*va, int);
+ case 1:
+ return va_arg(*va, long);
+ case 2:
+ return va_arg(*va, long long);
+ case 3:
+ default:
+ return (long long) va_arg(*va, void *);
+ }
+}
+
+void
+doprnt(Stream *sp, const char * restrict fmt, va_list va)
+{
+ char c;
+ va_list va2;
+ int base, sign, size;
+ char *s;
+
+ va_copy(va2, va);
+ while (( c = *fmt++) != '\0') {
+ if (c != '%') {
+ putch(sp, c);
+ continue;
+ }
+
+ sign = 0;
+ size = 0;
+flags:
+ switch (c = *fmt++) {
+ case 'l':
+ size++;
+ goto flags;
+ case 'o':
+ base = 8;
+ goto print_number;
+ case 'd':
+ sign = 1;
+ case 'u':
+ base = 10;
+ goto print_number;
+ case 'p':
+ size = 3;
+ case 'X':
+ case 'x':
+ base = 16;
+ print_number:
+ printn(sp, getnum(&va2, size), base, sign);
+ break;
+ case 's':
+ for (s = va_arg(va, char *); *s; s++)
+ putch(sp, *s);
+ break;
+ case 'c':
+ c = va_arg(va, int);
+ case '%':
+ putch(sp, c);
+ break;
+ case '\0':
+ goto out_loop;
+ }
+ }
+
+out_loop:
+ va_end(va2);
+}
diff --git a/src/libk/kprint.c b/src/libk/kprint.c
@@ -0,0 +1,16 @@
+#include <stdarg.h>
+
+#include "libk.h"
+
+int
+kprint(const char *fmt, ...)
+{
+ va_list ap;
+ Stream stream = {.fd = 1};
+
+ va_start(ap, fmt);
+ doprnt(&stream, fmt, ap);
+ va_end(ap);
+
+ return stream.cnt;
+}
diff --git a/src/libk/ksnprint.c b/src/libk/ksnprint.c
@@ -0,0 +1,20 @@
+#include <stdarg.h>
+#include <stddef.h>
+
+#include "libk.h"
+
+int
+ksnprint(char *str, size_t len, const char *fmt, ...)
+{
+ va_list ap;
+ Stream stream = {.fd = -1, .base = str, .len = len};
+
+ va_start(ap, fmt);
+ doprnt(&stream, fmt, ap);
+ va_end(ap);
+
+ if (stream.cnt < len)
+ str[stream.cnt++] = '\0';
+
+ return stream.cnt;
+}
diff --git a/src/libk/libk.h b/src/libk/libk.h
@@ -0,0 +1,11 @@
+#include <stddef.h>
+
+typedef struct stream Stream;
+struct stream {
+ int fd;
+ char *base;
+ size_t len;
+ size_t cnt;
+};
+
+extern void print(Stream *sp, const char * restrict fmt, va_list va);
diff --git a/src/libk/printk.c b/src/libk/printk.c
@@ -1,118 +0,0 @@
-
-#include <stdarg.h>
-#include <stddef.h>
-
-#include "../libc/syscall.h"
-
-static void
-putch(int c)
-{
- char ch = c;
- _write(1, &ch, 1);
-}
-
-static void
-printn(long long n, int base, int sign)
-{
- int first, d;
- unsigned long long div;
- const static char digits[] = "0123456789ABCDEF";
-
- switch (base) {
- case 8:
- div = 01000000000000000000000u;
- break;
- case 10:
- div = 10000000000000000000u;
- break;
- case 16:
- div = 0x1000000000000000u;
- break;
- }
-
- if (sign && n < 0) {
- n = -n;
- putch('-');
- }
-
- for (first = 1; div > 0; div /= base) {
- d = n / div;
- if (d == 0 && first && div != 1)
- continue;
- n -= d * div;
- putch(digits[d]);
- first = 0;
- }
-}
-
-static long long
-getnum(va_list *va, int size)
-{
- switch (size) {
- case 0:
- return va_arg(*va, int);
- case 1:
- return va_arg(*va, long);
- case 2:
- return va_arg(*va, long long);
- case 3:
- default:
- return (long long) va_arg(*va, void *);
- }
-}
-
-void
-printk(const char * restrict fmt, ...)
-{
- char c;
- va_list va;
- int base, sign, size;
- char *s;
-
- va_start(va, fmt);
- while (( c = *fmt++) != '\0') {
- if (c != '%') {
- putch(c);
- continue;
- }
-
- sign = 0;
- size = 0;
-flags:
- switch (c = *fmt++) {
- case 'l':
- size++;
- goto flags;
- case 'o':
- base = 8;
- goto print_number;
- case 'd':
- sign = 1;
- case 'u':
- base = 10;
- goto print_number;
- case 'p':
- size = 3;
- case 'X':
- case 'x':
- base = 16;
- print_number:
- printn(getnum(&va, size), base, sign);
- break;
- case 's':
- for (s = va_arg(va, char *); *s; s++)
- putch(*s);
- break;
- case 'c':
- c = va_arg(va, int);
- case '%':
- putch(c);
- break;
- case '\0':
- goto out_loop;
- }
- }
-
-out_loop:
- va_end(va);
-}
diff --git a/src/rmc.c b/src/rmc.c
@@ -4,7 +4,7 @@
static void
dumpregs(struct trapframe *fp)
{
- printk("x0=%llx\tx1=%llx\tx2=%llx\tx3=%llx\n"
+ kprint("x0=%llx\tx1=%llx\tx2=%llx\tx3=%llx\n"
"x4=%llx\tx5=%llx\tx6=%llx\tx7=%llx\n"
"x8=%llx\tx9=%llx\tx10=%llx\tx11=%llx\n"
"x12=%llx\tx13=%llx\tx14=%llx\tx15=%llx\n"
@@ -32,9 +32,9 @@ backtrace(struct trapframe *fp)
if (!bss->backtrace)
return;
- printk("backtrace:\n");
+ kprint("backtrace:\n");
for (bp = (void **) fp->x29; *bp; bp = (void **) *bp)
- printk("%p\n", bp[1]);
+ kprint("%p\n", bp[1]);
}
static void
@@ -44,10 +44,10 @@ dumpstack(struct trapframe *fp)
if (!bss->dumpstack)
return;
- printk("stack dump:\n");
+ kprint("stack dump:\n");
sp = fp->sp;
for (i = 1; i <= 16; i++)
- printk("%x%c", *sp++, (i % 4 == 0) ? '\n' : ' ');
+ kprint("%x%c", *sp++, (i % 4 == 0) ? '\n' : ' ');
}
static void
@@ -59,7 +59,7 @@ panicfmt(const char *msg, struct trapframe *fp)
*/
if (bss->in_panic != 1) {
bss->in_panic = 1;
- printk("panic: %s\n", msg);
+ kprint("panic: %s\n", msg);
dumpregs(fp);
backtrace(fp);