123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332 |
- #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;
- }
|