add fmt.c for print function

don't process 64-bit format such as '%llu' in print function.
This commit is contained in:
Hojun-Cho 2024-12-09 15:43:58 +09:00
parent c9c820840f
commit b1f7092fe2
6 changed files with 358 additions and 69 deletions

View File

@ -5,7 +5,7 @@ PROG = boot
SRCS = srt0.S gdt.S boot.c SRCS = srt0.S gdt.S boot.c
OBJS = srt0.o gdt.o boot.o 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) OBJS += $(ESRCS:.c=.o)
include $(SDIR)/Makefile.inc include $(SDIR)/Makefile.inc

View File

@ -2,6 +2,7 @@
// 0x60 Read/Write Data Port // 0x60 Read/Write Data Port
// 0x64 Read Status Register // 0x64 Read Status Register
// 0x64 Write Command Register // 0x64 Write Command Register
#define TABWIDTH 8
enum{ enum{
CON_PC, CON_PC,
@ -42,6 +43,16 @@ typedef struct{
u32 type; /* Type of block */ u32 type; /* Type of block */
} __attribute__((packed)) BIOSmmap; } __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 // gdt.S
extern volatile struct BIOSreg BIOSreg; extern volatile struct BIOSreg BIOSreg;

304
boot/fmt.c Normal file
View 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;
}

View File

@ -11,10 +11,17 @@ int comprobe(ConDev *d);
int comgetc(int dev); int comgetc(int dev);
void computc(int dev, int c); 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 // print.c
void putchar(int c); void putchar(int c);
void putstr(char *s, int l);
int getchar(void); int getchar(void);
void print(const char *fmt, ...); int print(char *fmt, ...);
int snprint(char *buf, int len, char *fmt, ...);
// a20.c // a20.c
void a20up(void); void a20up(void);

View File

@ -42,13 +42,13 @@ dumpmem(BIOSmmap *m)
ulong tot = 0; ulong tot = 0;
for(BIOSmmap *p=m; p->type != MAP_END; ++p){ for(BIOSmmap *p=m; p->type != MAP_END; ++p){
print("MEM %u type %u size %lldKB at 0x%llx\n", print("MEM % 2ud type %ud size % 10udKB at %08x:%08x\n",
p-m, p->type, p->size/1024, p->addr); p-m, p->type, (uint)(p->size/1024), (uint)(p->addr>>32), (uint)p->addr);
if(p->type == MAP_FREE) if(p->type == MAP_FREE)
tot += p->size/1024; tot += p->size/1024;
} }
print("RAM low:%dKB high:%dKB\n", cnvmem, extmem); print("RAM low:%udKB high:%udKB\n", cnvmem, extmem);
print("Total free memory: %dKB\n", tot); print("Total free memory: %udKB\n", tot);
} }
static int static int
@ -77,6 +77,5 @@ memprobe(void)
extmem += m->size/1024; extmem += m->size/1024;
} }
dumpmem(biosmmap); dumpmem(biosmmap);
print("A20:%d", isa20done()); print("A20:%s\n", isa20done() ? "ok" : "no");
} }

View File

@ -2,54 +2,35 @@
#include "dat.h" #include "dat.h"
#include "fn.h" #include "fn.h"
#define TABWIDTH 4 #define BUFSIZE 1024
static void conputc(int c); static void conputc(int);
static int congetc(void); 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 int
print(const char *fmt, ...) print(char *fmt, ...)
{ {
char buf[BUFSIZE], *p;
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
doprint(putchar, fmt, args); p = doprint(buf, buf+sizeof(buf), fmt, args);
va_end(args); va_end(args);
putstr(buf, p-buf);
return p-buf;
} }
static void int
doprint(void (*put)(int), const char *s, va_list ap) snprint(char *buf, int len, char *fmt, ...)
{ {
while(*s){ char *p;
if(*s != '%'){ va_list args;
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;
}
}
va_start(args, fmt);
p = doprint(buf, buf+len, fmt, args);
va_end(args);
return p-buf;
}
int int
getchar(void) getchar(void)
@ -65,6 +46,13 @@ getchar(void)
return c; return c;
} }
void
putstr(char *s, int l)
{
while(l--)
putchar(*s++);
}
void void
putchar(int c) putchar(int c)
{ {
@ -72,24 +60,20 @@ putchar(int c)
case '\177': case '\177':
conputc('\b'); conputc('\b');
conputc(' '); conputc(' ');
break;
case '\b': case '\b':
conputc('\b'); conputc('\b');
if(pos > 0)
--pos;
break; break;
case '\t': case '\t':
do{ for(int i = 0; i < TABWIDTH; ++i)
conputc(' '); conputc(' ');
}while(++pos % TABWIDTH);
break; break;
case '\n': case '\n':
case '\r': case '\r':
conputc(c); conputc(c);
pos = 0;
break; break;
default: default:
conputc(c); conputc(c);
++pos;
break; break;
} }
} }
@ -109,19 +93,3 @@ congetc(void)
{ {
return con->getc(con->dev); 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);
}