add fmt.c for print function
don't process 64-bit format such as '%llu' in print function.
This commit is contained in:
parent
c9c820840f
commit
b1f7092fe2
@ -5,7 +5,7 @@ PROG = boot
|
||||
SRCS = srt0.S gdt.S boot.c
|
||||
OBJS = srt0.o gdt.o boot.o
|
||||
|
||||
ESRCS = pccon.c sricon.c print.c a20.c time.c mem.c
|
||||
ESRCS = pccon.c sricon.c print.c fmt.c a20.c time.c mem.c
|
||||
OBJS += $(ESRCS:.c=.o)
|
||||
|
||||
include $(SDIR)/Makefile.inc
|
||||
|
||||
11
boot/dat.h
11
boot/dat.h
@ -2,6 +2,7 @@
|
||||
// 0x60 Read/Write Data Port
|
||||
// 0x64 Read Status Register
|
||||
// 0x64 Write Command Register
|
||||
#define TABWIDTH 8
|
||||
|
||||
enum{
|
||||
CON_PC,
|
||||
@ -42,6 +43,16 @@ typedef struct{
|
||||
u32 type; /* Type of block */
|
||||
} __attribute__((packed)) BIOSmmap;
|
||||
|
||||
// fmt.c
|
||||
typedef struct{
|
||||
int ucase;
|
||||
int padch;
|
||||
char *p;
|
||||
char *ep;
|
||||
int f1, f2, f3;
|
||||
va_list ap;
|
||||
}Op;
|
||||
|
||||
// gdt.S
|
||||
extern volatile struct BIOSreg BIOSreg;
|
||||
|
||||
|
||||
304
boot/fmt.c
Normal file
304
boot/fmt.c
Normal file
@ -0,0 +1,304 @@
|
||||
#include <u.h>
|
||||
#include "dat.h"
|
||||
#include "fn.h"
|
||||
|
||||
#define MAXCON 30
|
||||
#define IDIGIT 30
|
||||
|
||||
enum{
|
||||
FLONG = (1<<0),
|
||||
FSHORT = (1<<2),
|
||||
FUNSIGN = (1<<3),
|
||||
};
|
||||
|
||||
static Op put(Op, int);
|
||||
static Op noconv(Op);
|
||||
static Op cconv(Op);
|
||||
static Op dconv(Op);
|
||||
static Op hconv(Op);
|
||||
static Op lconv(Op);
|
||||
static Op sconv(Op);
|
||||
static Op uconv(Op);
|
||||
static Op xconv(Op);
|
||||
static Op Xconv(Op);
|
||||
static Op percent(Op);
|
||||
|
||||
static Op (*fmtconv[MAXCON])(Op) = {
|
||||
noconv,
|
||||
cconv, dconv, hconv, lconv,
|
||||
sconv, uconv, xconv, Xconv,
|
||||
percent,
|
||||
};
|
||||
|
||||
int fmtindex[128] = {
|
||||
['c'] = 1,
|
||||
['d'] = 2,
|
||||
['h'] = 3,
|
||||
['l'] = 4,
|
||||
['s'] = 5,
|
||||
['u'] = 6,
|
||||
['x'] = 7,
|
||||
['X'] = 8,
|
||||
['%'] = 9,
|
||||
};
|
||||
int convcnt = 11;
|
||||
|
||||
int
|
||||
strlen(char *s)
|
||||
{
|
||||
char *p = s;
|
||||
|
||||
while(*p)
|
||||
++p;
|
||||
return p-s;
|
||||
}
|
||||
|
||||
int
|
||||
fmtinstall(int c, Op (*f)(Op))
|
||||
{
|
||||
c &= 0177;
|
||||
if(fmtindex[c] == 0){
|
||||
if(convcnt + 1 >= MAXCON)
|
||||
return -1;
|
||||
fmtindex[c] = convcnt++;
|
||||
}
|
||||
fmtconv[fmtindex[c]] = f;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char*
|
||||
doprint(char *p, char *ep, char *fmt, va_list ap)
|
||||
{
|
||||
int sf1, c;
|
||||
Op o = { .p = p, .ep = ep, .ap = ap };
|
||||
|
||||
while(1){
|
||||
c = *fmt++;
|
||||
if(c != '%'){
|
||||
if(c == 0){
|
||||
if(o.p < o.ep)
|
||||
*o.p = 0;
|
||||
return o.p;
|
||||
}
|
||||
o = put(o, c);
|
||||
continue;
|
||||
}
|
||||
o.f2 = -1;
|
||||
o.f1 = o.f3 = 0;
|
||||
o.padch = sf1 = 0;
|
||||
c = *fmt++;
|
||||
if(c == '-'){
|
||||
sf1 = 1;
|
||||
c = *fmt++;
|
||||
}else if(c == '0' || c == ' '){
|
||||
o.padch = c;
|
||||
c = *fmt++;
|
||||
}
|
||||
while(c >= '0' && c <= '9'){
|
||||
o.f1 = o.f1*10 + c-'0';
|
||||
c = *fmt++;
|
||||
}
|
||||
if(sf1)
|
||||
o.f1 = -o.f1;
|
||||
if(c != '.')
|
||||
goto conv;
|
||||
c = *fmt++;
|
||||
while(c >= '0' && c <= '9'){
|
||||
if(o.f2 < 0)
|
||||
o.f2 = 0;
|
||||
o.f2 = o.f2*10 + c-'0';
|
||||
c = *fmt++;
|
||||
}
|
||||
conv:
|
||||
if(c == 0)
|
||||
fmt -= 1;
|
||||
o = (*fmtconv[fmtindex[c&0177]])(o);
|
||||
if(o.f3){
|
||||
c = *fmt++;
|
||||
goto conv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Op
|
||||
strconv(char *o, Op op, int f1, int f2)
|
||||
{
|
||||
int n, c;
|
||||
char *p;
|
||||
|
||||
n = strlen(o);
|
||||
if(f1 >= 0)
|
||||
while(n < f1){
|
||||
op = put(op, op.padch);
|
||||
n += 1;
|
||||
}
|
||||
for(p=o; (c = *p++);)
|
||||
if(f2){
|
||||
op = put(op, c);
|
||||
f2 -= 1;
|
||||
}
|
||||
if(f1 < 0){
|
||||
f1 = -f1;
|
||||
while(n < f1){
|
||||
op = put(op, ' ');
|
||||
n += 1;
|
||||
}
|
||||
}
|
||||
return op;
|
||||
}
|
||||
|
||||
static Op
|
||||
numconv(Op op, int base)
|
||||
{
|
||||
char b[IDIGIT];
|
||||
int i,f,n;
|
||||
long v;
|
||||
short h;
|
||||
|
||||
i = IDIGIT-1;
|
||||
f = 0;
|
||||
b[i] = 0;
|
||||
switch(op.f3 & (FLONG|FSHORT|FUNSIGN)){
|
||||
case FLONG:
|
||||
v = va_arg(op.ap, long);
|
||||
break;
|
||||
case FUNSIGN|FLONG:
|
||||
v = va_arg(op.ap, ulong);
|
||||
break;
|
||||
case FSHORT:
|
||||
v = h = va_arg(op.ap, short);
|
||||
break;
|
||||
case FUNSIGN|FSHORT:
|
||||
h = va_arg(op.ap, ushort);
|
||||
v = (ushort)h;
|
||||
break;
|
||||
case FUNSIGN:
|
||||
v = va_arg(op.ap, unsigned);
|
||||
break;
|
||||
default:
|
||||
v = va_arg(op.ap, long);
|
||||
break;
|
||||
}
|
||||
if((op.f3 & FUNSIGN) && v < 0){
|
||||
v = -v;
|
||||
f = 1;
|
||||
}
|
||||
while(--i){
|
||||
n = v % base;
|
||||
n += '0';
|
||||
if(n > '9'){
|
||||
n += 'a' - ('9'+1);
|
||||
if(op.ucase)
|
||||
n += 'A'-'a';
|
||||
}
|
||||
b[i] = n;
|
||||
v = (ulong)v / base;
|
||||
if(i < 2)
|
||||
break;
|
||||
if(op.f2 >= 0 && i >= IDIGIT - op.f2)
|
||||
continue;
|
||||
if(v <= 0)
|
||||
break;
|
||||
}
|
||||
if(f)
|
||||
b[--i] = '-';
|
||||
op.f3 = 0;
|
||||
return strconv(b+i, op, op.f1, -1);
|
||||
}
|
||||
|
||||
static Op
|
||||
noconv(Op op)
|
||||
{
|
||||
return strconv("***ERROR: noconv***", op, 0, -1);
|
||||
}
|
||||
|
||||
static Op
|
||||
cconv(Op op)
|
||||
{
|
||||
char b[2];
|
||||
|
||||
b[0] = va_arg(op.ap, char);
|
||||
b[1] = 0;
|
||||
return strconv(b, op, op.f1, -1);
|
||||
}
|
||||
|
||||
static Op
|
||||
dconv(Op op)
|
||||
{
|
||||
return numconv(op, 10);
|
||||
}
|
||||
|
||||
static Op
|
||||
hconv(Op op)
|
||||
{
|
||||
op.f3 |= FSHORT;
|
||||
return op;
|
||||
}
|
||||
|
||||
static Op
|
||||
lconv(Op op)
|
||||
{
|
||||
op.f3 |= FLONG;
|
||||
return op;
|
||||
}
|
||||
|
||||
static Op
|
||||
uconv(Op op)
|
||||
{
|
||||
op.f3 |= FUNSIGN;
|
||||
return op;
|
||||
}
|
||||
|
||||
static Op
|
||||
sconv(Op op)
|
||||
{
|
||||
char *p;
|
||||
|
||||
p = va_arg(op.ap, char*);
|
||||
return strconv(p?p:"<nil>", op, op.f1, op.f2);
|
||||
}
|
||||
|
||||
static Op
|
||||
xconv(Op op)
|
||||
{
|
||||
return numconv(op, 16);
|
||||
}
|
||||
|
||||
static Op
|
||||
Xconv(Op op)
|
||||
{
|
||||
op.ucase = 1;
|
||||
op = numconv(op, 16);
|
||||
op.ucase = 0;
|
||||
return op;
|
||||
}
|
||||
|
||||
static Op
|
||||
percent(Op op)
|
||||
{
|
||||
return put(op, '%');
|
||||
}
|
||||
|
||||
static Op
|
||||
put(Op o, int c)
|
||||
{
|
||||
static int pos;
|
||||
int opos;
|
||||
|
||||
if(c == 0)
|
||||
return o;
|
||||
if(c == '\t'){
|
||||
opos = pos;
|
||||
pos = (opos+TABWIDTH) & (~(TABWIDTH-1));
|
||||
while(opos++ < pos && o.p < o.ep)
|
||||
*o.p++ = ' ';
|
||||
return o;
|
||||
}
|
||||
if(o.p < o.ep){
|
||||
*o.p++ = c;
|
||||
pos++;
|
||||
}
|
||||
if(c == '\n')
|
||||
pos = 0;
|
||||
return o;
|
||||
}
|
||||
@ -11,10 +11,17 @@ int comprobe(ConDev *d);
|
||||
int comgetc(int dev);
|
||||
void computc(int dev, int c);
|
||||
|
||||
// fmt.c
|
||||
int fmtinstall(int c, Op (*f)(Op));
|
||||
char *doprint(char *p, char *ep, char *fmt, va_list ap);
|
||||
int strlen(char *s);
|
||||
|
||||
// print.c
|
||||
void putchar(int c);
|
||||
void putstr(char *s, int l);
|
||||
int getchar(void);
|
||||
void print(const char *fmt, ...);
|
||||
int print(char *fmt, ...);
|
||||
int snprint(char *buf, int len, char *fmt, ...);
|
||||
|
||||
// a20.c
|
||||
void a20up(void);
|
||||
|
||||
15
boot/mem.c
15
boot/mem.c
@ -42,13 +42,13 @@ dumpmem(BIOSmmap *m)
|
||||
ulong tot = 0;
|
||||
|
||||
for(BIOSmmap *p=m; p->type != MAP_END; ++p){
|
||||
print("MEM %u type %u size %lldKB at 0x%llx\n",
|
||||
p-m, p->type, p->size/1024, p->addr);
|
||||
print("MEM % 2ud type %ud size % 10udKB at %08x:%08x\n",
|
||||
p-m, p->type, (uint)(p->size/1024), (uint)(p->addr>>32), (uint)p->addr);
|
||||
if(p->type == MAP_FREE)
|
||||
tot += p->size/1024;
|
||||
}
|
||||
print("RAM low:%dKB high:%dKB\n", cnvmem, extmem);
|
||||
print("Total free memory: %dKB\n", tot);
|
||||
print("RAM low:%udKB high:%udKB\n", cnvmem, extmem);
|
||||
print("Total free memory: %udKB\n", tot);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -70,13 +70,12 @@ memprobe(void)
|
||||
m->type = MAP_END;
|
||||
for(m = biosmmap; m->type != MAP_END; ++m){
|
||||
if(m->type != MAP_FREE || m->size <= 0)
|
||||
continue;
|
||||
continue;
|
||||
if(m->addr < IOMEM_BEGIN)
|
||||
cnvmem = MAX(cnvmem, m->addr + m->size)/1024;
|
||||
if(m->addr >= IOMEM_END)
|
||||
extmem += m->size/1024;
|
||||
}
|
||||
dumpmem(biosmmap);
|
||||
print("A20:%d", isa20done());
|
||||
}
|
||||
|
||||
print("A20:%s\n", isa20done() ? "ok" : "no");
|
||||
}
|
||||
86
boot/print.c
86
boot/print.c
@ -2,61 +2,42 @@
|
||||
#include "dat.h"
|
||||
#include "fn.h"
|
||||
|
||||
#define TABWIDTH 4
|
||||
#define BUFSIZE 1024
|
||||
|
||||
static void conputc(int c);
|
||||
static void conputc(int);
|
||||
static int congetc(void);
|
||||
static void doprint(void (*put)(int), const char *fmt, va_list ap);
|
||||
static void putint(void (*put)(int), int n, const char *sym, int base);
|
||||
static int pos = 0;
|
||||
|
||||
void
|
||||
print(const char *fmt, ...)
|
||||
int
|
||||
print(char *fmt, ...)
|
||||
{
|
||||
char buf[BUFSIZE], *p;
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
doprint(putchar, fmt, args);
|
||||
p = doprint(buf, buf+sizeof(buf), fmt, args);
|
||||
va_end(args);
|
||||
putstr(buf, p-buf);
|
||||
return p-buf;
|
||||
}
|
||||
|
||||
static void
|
||||
doprint(void (*put)(int), const char *s, va_list ap)
|
||||
int
|
||||
snprint(char *buf, int len, char *fmt, ...)
|
||||
{
|
||||
while(*s){
|
||||
if(*s != '%'){
|
||||
put(*s++);
|
||||
continue;
|
||||
}
|
||||
++s;
|
||||
switch(*s){
|
||||
case 'd':
|
||||
putint(put, va_arg(ap,int), "0123456789", 10);
|
||||
break;
|
||||
case 'x':
|
||||
putint(put, va_arg(ap,int), "0123456789abcdef", 16);
|
||||
break;
|
||||
case 'X':
|
||||
putint(put, va_arg(ap,int), "0123456789ABCDEF", 16);
|
||||
break;
|
||||
case 's':
|
||||
for(char *p=va_arg(ap,char*); *p; ++p)
|
||||
put(*p);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
++s;
|
||||
}
|
||||
}
|
||||
char *p;
|
||||
va_list args;
|
||||
|
||||
va_start(args, fmt);
|
||||
p = doprint(buf, buf+len, fmt, args);
|
||||
va_end(args);
|
||||
return p-buf;
|
||||
}
|
||||
|
||||
int
|
||||
getchar(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = congetc();
|
||||
c = congetc();
|
||||
if(c == '\r')
|
||||
c = '\n';
|
||||
if((c < ' ' && c != '\n') || c == '\177')
|
||||
@ -65,6 +46,13 @@ getchar(void)
|
||||
return c;
|
||||
}
|
||||
|
||||
void
|
||||
putstr(char *s, int l)
|
||||
{
|
||||
while(l--)
|
||||
putchar(*s++);
|
||||
}
|
||||
|
||||
void
|
||||
putchar(int c)
|
||||
{
|
||||
@ -72,24 +60,20 @@ putchar(int c)
|
||||
case '\177':
|
||||
conputc('\b');
|
||||
conputc(' ');
|
||||
break;
|
||||
case '\b':
|
||||
conputc('\b');
|
||||
if(pos > 0)
|
||||
--pos;
|
||||
break;
|
||||
case '\t':
|
||||
do{
|
||||
for(int i = 0; i < TABWIDTH; ++i)
|
||||
conputc(' ');
|
||||
}while(++pos % TABWIDTH);
|
||||
break;
|
||||
case '\n':
|
||||
case '\r':
|
||||
conputc(c);
|
||||
pos = 0;
|
||||
break;
|
||||
default:
|
||||
conputc(c);
|
||||
++pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -108,20 +92,4 @@ static int
|
||||
congetc(void)
|
||||
{
|
||||
return con->getc(con->dev);
|
||||
}
|
||||
|
||||
static void
|
||||
putint(void (*put)(int), int n, const char *sym, int base)
|
||||
{
|
||||
int i;
|
||||
char buf[16];
|
||||
|
||||
i = 0;
|
||||
do{
|
||||
buf[i++] = n%base;
|
||||
n /= base;
|
||||
}while(n);
|
||||
do{
|
||||
put((int)sym[(int)buf[--i]]);
|
||||
}while(i);
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user