提交 6f850620 创建 作者: Silas Boyd-Wickizer's avatar Silas Boyd-Wickizer

The jos/HiStar/Corey vprintfmt.

This supports width, precision, length, and padding.
上级 523eb643
......@@ -35,6 +35,7 @@ OBJS = \
e1000.o \
exec.o \
file.o \
fmt.o \
fs.o \
ioapic.o \
lapic.o \
......
......@@ -13,7 +13,10 @@
#include "queue.h"
#include "proc.h"
#include "traps.h"
#include "lib.h"
#include <stdarg.h>
#include "fmt.h"
#include <stddef.h>
#define BACKSPACE 0x100
......@@ -25,32 +28,6 @@ static struct {
} cons;
static void
printint(void (*putch) (void*, char), void *putarg,
u64 xx, int base, int sign)
{
static char digits[] = "0123456789abcdef";
char buf[16];
int i;
u64 x;
if(sign && (sign = xx < 0))
x = -xx;
else
x = xx;
i = 0;
do{
buf[i++] = digits[x % base];
}while((x /= base) != 0);
if(sign)
buf[i++] = '-';
while(--i >= 0)
putch(putarg, buf[i]);
}
static void
consputc(int c)
{
if(panicked){
......@@ -77,72 +54,11 @@ consputc(int c)
// Print to the console.
static void
writecons(void *arg, char c)
writecons(int c, void *arg)
{
consputc(c);
}
// Only understands %d, %u, %x, %s, %lx, %lu.
void
vprintfmt(void (*putch) (void*, char), void *putarg,
const char *fmt, va_list ap)
{
char *s;
int c, i, state;
state = 0;
for(i = 0; fmt[i]; i++){
c = fmt[i] & 0xff;
if(state == 0){
if(c == '%'){
state = '%';
} else {
putch(putarg, c);
}
} else if(state == '%'){
if(c == 'd') {
printint(putch, putarg, va_arg(ap, u32), 10, 1);
} else if(c == 'u') {
printint(putch, putarg, va_arg(ap, u32), 10, 0);
} else if(c == 'x') {
printint(putch, putarg, va_arg(ap, u32), 16, 0);
} else if(c == 'l') {
state = 'l';
continue;
} else if(c == 's'){
s = (char*) va_arg(ap, char*);
if(s == 0)
s = "(null)";
while(*s != 0){
putch(putarg, *s);
s++;
}
} else if(c == 'c'){
putch(putarg, va_arg(ap, u32));
} else if(c == '%'){
putch(putarg, c);
} else {
// Unknown % sequence. Print it to draw attention.
putch(putarg, '%');
putch(putarg, c);
}
state = 0;
} else if(state == 'l') {
if(c == 'x') {
printint(putch, putarg, va_arg(ap, u64), 16, 0);
}
else if(c == 'u') {
printint(putch, putarg, va_arg(ap, u64), 10, 0);
}
else {
// Unknown % sequence. Print it to draw attention.
putch(putarg, '%');
putch(putarg, c);
}
state = 0;
}
}
}
// Print to a buffer.
struct bufstate {
......@@ -151,7 +67,7 @@ struct bufstate {
};
static void
writebuf(void *arg, char c)
writebuf(int c, void *arg)
{
struct bufstate *bs = arg;
if (bs->p < bs->e) {
......@@ -204,7 +120,7 @@ puts(const char *s)
ep = p+strlen(s);
for (; p < ep; p++)
writecons(NULL, *p);
writecons(*p, NULL);
}
......
#include "types.h"
#include "kernel.h"
#include <stddef.h>
#include <stdarg.h>
#include "fmt.h"
//
// Print a number (base <= 16) in reverse order,
// using specified putch function and associated pointer putdat.
//
static void
printnum (void (*putch) (int, void *), void *putdat,
unsigned long long num, unsigned base, int width, int padc)
{
// recursion a bad idea here
char buf[68], *x;
for (x = buf; num; num /= base)
*x++ = "0123456789abcdef"[num % base];
if (x == buf)
*x++ = '0';
if (padc != '-')
for (; width > x - buf; width--)
putch (padc, putdat);
for (; x > buf; width--)
putch (*--x, putdat);
if (padc == '-')
for (; width > 0; width--)
putch (' ', putdat);
}
// Get an unsigned int of various possible sizes from a varargs list,
// depending on the lflag parameter.
//
// These cannot be functions without autoconf-like glue, unfortunately.
// gcc-3.4.5 on x86_64 passes va_list by reference, and doesn't like the
// type (va_list*), and gcc-3.4.6 on i386 passes va_list by value, and
// does handle the type (va_list*).
//
// [http://www.opengroup.org/onlinepubs/009695399/basedefs/stdarg.h.html]
// The object ap may be passed as an argument to another function;
// if that function invokes the va_arg() macro with parameter ap,
// the value of ap in the calling function is unspecified and shall
// be passed to the va_end() macro prior to any further reference to ap.
#define getuint(ap, lflag) \
({ \
long long __v; \
if (lflag >= 2) \
__v = va_arg (ap, unsigned long long); \
else if (lflag) \
__v = va_arg (ap, unsigned long); \
else \
__v = va_arg (ap, unsigned int); \
__v; \
})
// Same as getuint but signed - can't use getuint
// because of sign extension
#define getint(ap, lflag) \
({ \
long long __v; \
if (lflag >= 2) \
__v = va_arg (ap, long long); \
else if (lflag) \
__v = va_arg (ap, long); \
else \
__v = va_arg (ap, int); \
__v; \
})
void
vprintfmt(void (*putch)(int, void*), void *putdat,
const char *fmt, va_list ap)
{
register const char *p;
register int ch;
unsigned long long num;
int base, lflag, width, precision, altflag;
char padc;
while (1) {
while ((ch = *(unsigned char *) fmt++) != '%') {
if (ch == '\0')
return;
putch(ch, putdat);
}
// Process a %-escape sequence
padc = ' ';
width = -1;
precision = -1;
lflag = 0;
altflag = 0;
reswitch:
switch (ch = *(unsigned char *) fmt++) {
// flag to pad on the right
case '-':
padc = '-';
goto reswitch;
// flag to pad with 0's instead of spaces
case '0':
padc = '0';
goto reswitch;
// width field
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
for (precision = 0;; ++fmt) {
precision = precision * 10 + ch - '0';
ch = *fmt;
if (ch < '0' || ch > '9')
break;
}
goto process_precision;
case '*':
precision = va_arg (ap, int);
goto process_precision;
case '.':
if (width < 0)
width = 0;
goto reswitch;
case '#':
altflag = 1;
goto reswitch;
process_precision:
if (width < 0)
width = precision, precision = -1;
goto reswitch;
// long flag (doubled for long long)
case 'l':
lflag++;
goto reswitch;
// size_t
case 'z':
if (sizeof(size_t) == sizeof(long))
lflag = 1;
else if (sizeof(size_t) == sizeof(long long))
lflag = 2;
else
lflag = 0;
goto reswitch;
// character
case 'c':
putch (va_arg (ap, int), putdat);
break;
// string
case 's':
if ((p = va_arg (ap, char *)) == NULL)
p = "(null)";
if (width > 0 && padc != '-')
for (width -= strlen (p); width > 0; width--)
putch (padc, putdat);
for (; (ch = *p++) != '\0' && (precision < 0 || --precision >= 0);
width--)
if (altflag && (ch < ' ' || ch > '~'))
putch ('?', putdat);
else
putch (ch, putdat);
for (; width > 0; width--)
putch (' ', putdat);
break;
// binary
case 'b':
num = getint (ap, lflag);
base = 2;
goto number;
// (signed) decimal
case 'd':
num = getint (ap, lflag);
if ((long long) num < 0) {
putch ('-', putdat);
num = -(long long) num;
}
base = 10;
goto number;
// unsigned decimal
case 'u':
num = getuint (ap, lflag);
base = 10;
goto number;
// (unsigned) octal
case 'o':
num = getuint (ap, lflag);
base = 8;
goto number;
// pointer
case 'p':
putch ('0', putdat);
putch ('x', putdat);
num = (unsigned long long)
(uptr) va_arg (ap, void *);
base = 16;
goto number;
// (unsigned) hexadecimal
case 'x':
num = getuint (ap, lflag);
base = 16;
number:
printnum (putch, putdat, num, base, MAX(width, 0), padc);
break;
// unrecognized escape sequence - just print it literally
default:
putch ('%', putdat);
while (lflag-- > 0)
putch ('l', putdat);
/* FALLTHROUGH */
// escaped '%' character
case '%':
putch (ch, putdat);
}
}
}
void vprintfmt(void (*putch)(int, void*), void *putdat,
const char *fmt, va_list ap);
#include "mmu.h"
#include "lib.h"
#define KBASE 0xFFFFFF0000000000ull
#define USERTOP 0x0000800000000000ull
......@@ -6,18 +7,9 @@
#define KCSEG (2<<3) /* kernel code segment */
#define KDSEG (3<<3) /* kernel data segment */
#define NULL ((void *)0)
static inline uptr v2p(void *a) { return (uptr) a - KBASE; }
static inline void *p2v(uptr a) { return (void *) a + KBASE; }
#define NELEM(x) (sizeof(x)/sizeof((x)[0]))
#define cmpswap(ptr, old, new) __sync_bool_compare_and_swap(ptr, old, new)
#define subfetch(ptr, val) __sync_sub_and_fetch(ptr, val)
#define fetchadd(ptr, val) __sync_fetch_and_add(ptr, val)
#define __offsetof offsetof
struct trapframe;
struct spinlock;
struct condvar;
......
#define NULL ((void *)0)
#define MIN(_a, _b) \
({ \
__typeof__(_a) __a = (_a); \
__typeof__(_b) __b = (_b); \
__a <= __b ? __a : __b; \
})
#define MAX(_a, _b) \
({ \
__typeof__(_a) __a = (_a); \
__typeof__(_b) __b = (_b); \
__a >= __b ? __a : __b; \
})
#define NELEM(x) (sizeof(x)/sizeof((x)[0]))
#define cmpswap(ptr, old, new) __sync_bool_compare_and_swap(ptr, old, new)
#define subfetch(ptr, val) __sync_sub_and_fetch(ptr, val)
#define fetchadd(ptr, val) __sync_fetch_and_add(ptr, val)
#define __offsetof offsetof
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论