diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/boot/bitsy/donprint.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/boot/bitsy/donprint.c')
-rwxr-xr-x | sys/src/boot/bitsy/donprint.c | 332 |
1 files changed, 332 insertions, 0 deletions
diff --git a/sys/src/boot/bitsy/donprint.c b/sys/src/boot/bitsy/donprint.c new file mode 100755 index 000000000..4125e6904 --- /dev/null +++ b/sys/src/boot/bitsy/donprint.c @@ -0,0 +1,332 @@ +#include "u.h" +#include "lib.h" + +#define PTR sizeof(char*) +#define SHORT sizeof(int) +#define INT sizeof(int) +#define LONG sizeof(long) +#define IDIGIT 30 +#define MAXCON 30 + +#define FLONG (1<<0) +#define FSHORT (1<<1) +#define FUNSIGN (1<<2) + +typedef struct Op Op; +struct Op +{ + char *p; + char *ep; + void *argp; + int f1; + int f2; + int f3; +}; + +static int noconv(Op*); +static int cconv(Op*); +static int dconv(Op*); +static int hconv(Op*); +static int lconv(Op*); +static int oconv(Op*); +static int sconv(Op*); +static int uconv(Op*); +static int xconv(Op*); +static int Xconv(Op*); +static int percent(Op*); + +static +int (*fmtconv[MAXCON])(Op*) = +{ + noconv, + cconv, dconv, hconv, lconv, + oconv, sconv, uconv, xconv, + Xconv, percent, +}; +static +char fmtindex[128] = +{ + ['c'] 1, + ['d'] 2, + ['h'] 3, + ['l'] 4, + ['o'] 5, + ['s'] 6, + ['u'] 7, + ['x'] 8, + ['X'] 9, + ['%'] 10, +}; + +static int convcount = { 11 }; +static int ucase; + +static void +PUT(Op *o, int c) +{ + static int pos; + int opos; + + if(c == '\t'){ + opos = pos; + pos = (opos+8) & ~7; + while(opos++ < pos && o->p < o->ep) + *o->p++ = ' '; + return; + } + if(o->p < o->ep){ + *o->p++ = c; + pos++; + } + if(c == '\n') + pos = 0; +} + +int +fmtinstall(char c, int (*f)(Op*)) +{ + + c &= 0177; + if(fmtindex[c] == 0) { + if(convcount >= MAXCON) + return 1; + fmtindex[c] = convcount++; + } + fmtconv[fmtindex[c]] = f; + return 0; +} + +char* +donprint(char *p, char *ep, char *fmt, void *argp) +{ + int sf1, c; + Op o; + + o.p = p; + o.ep = ep; + o.argp = argp; + +loop: + c = *fmt++; + if(c != '%') { + if(c == 0) { + if(o.p < o.ep) + *o.p = 0; + return o.p; + } + PUT(&o, c); + goto loop; + } + o.f1 = 0; + o.f2 = -1; + o.f3 = 0; + c = *fmt++; + sf1 = 0; + if(c == '-') { + sf1 = 1; + 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 l1; + c = *fmt++; + while(c >= '0' && c <= '9') { + if(o.f2 < 0) + o.f2 = 0; + o.f2 = o.f2*10 + c-'0'; + c = *fmt++; + } +l1: + if(c == 0) + fmt--; + c = (*fmtconv[fmtindex[c&0177]])(&o); + if(c < 0) { + o.f3 |= -c; + c = *fmt++; + goto l1; + } + o.argp = (char*)o.argp + c; + goto loop; +} + +void +strconv(char *o, Op *op, int f1, int f2) +{ + int n, c; + char *p; + + n = strlen(o); + if(f1 >= 0) + while(n < f1) { + PUT(op, ' '); + n++; + } + for(p=o; c = *p++;) + if(f2 != 0) { + PUT(op, c); + f2--; + } + if(f1 < 0) { + f1 = -f1; + while(n < f1) { + PUT(op, ' '); + n++; + } + } +} + +int +numbconv(Op *op, int base) +{ + char b[IDIGIT]; + int i, f, n, r; + long v; + short h; + + f = 0; + switch(op->f3 & (FLONG|FSHORT|FUNSIGN)) { + case FLONG: + v = *(long*)op->argp; + r = LONG; + break; + + case FUNSIGN|FLONG: + v = *(ulong*)op->argp; + r = LONG; + break; + + case FSHORT: + h = *(int*)op->argp; + v = h; + r = SHORT; + break; + + case FUNSIGN|FSHORT: + h = *(int*)op->argp; + v = (ushort)h; + r = SHORT; + break; + + default: + v = *(int*)op->argp; + r = INT; + break; + + case FUNSIGN: + v = *(unsigned*)op->argp; + r = INT; + break; + } + if(!(op->f3 & FUNSIGN) && v < 0) { + v = -v; + f = 1; + } + b[IDIGIT-1] = 0; + for(i = IDIGIT-2;; i--) { + n = (ulong)v % base; + n += '0'; + if(n > '9'){ + n += 'a' - ('9'+1); + if(ucase) + n += 'A'-'a'; + } + b[i] = n; + if(i < 2) + break; + v = (ulong)v / base; + if(op->f2 >= 0 && i >= IDIGIT-op->f2) + continue; + if(v <= 0) + break; + } + if(f) + b[--i] = '-'; + strconv(b+i, op, op->f1, -1); + return r; +} + +static int +noconv(Op *op) +{ + + strconv("***", op, 0, -1); + return 0; +} + +static int +cconv(Op *op) +{ + char b[2]; + + b[0] = *(int*)op->argp; + b[1] = 0; + strconv(b, op, op->f1, -1); + return INT; +} + +static int +dconv(Op *op) +{ + return numbconv(op, 10); +} + +static int +hconv(Op*) +{ + return -FSHORT; +} + +static int +lconv(Op*) +{ + return -FLONG; +} + +static int +oconv(Op *op) +{ + return numbconv(op, 8); +} + +static int +sconv(Op *op) +{ + strconv(*(char**)op->argp, op, op->f1, op->f2); + return PTR; +} + +static int +uconv(Op*) +{ + return -FUNSIGN; +} + +static int +xconv(Op *op) +{ + return numbconv(op, 16); +} + +static int +Xconv(Op *op) +{ + int r; + + ucase = 1; + r = numbconv(op, 16); + ucase = 0; + return r; +} + +static int +percent(Op *op) +{ + + PUT(op, '%'); + return 0; +} |