diff --git a/sys/man/1/pc b/sys/man/1/pc index 90534e243..9c86eba9a 100644 --- a/sys/man/1/pc +++ b/sys/man/1/pc @@ -65,6 +65,9 @@ Display \fIn\fR in decimal. .I hex(n) Display \fIn\fR in hexadecimal. .TP +.I pb(n, b) +Display \fIn\fR in base \fIb\fR (currently must be one of 0, 2, 8, 10, 16; 0 uses the defined output base). +.TP .I abs(n) Absolute value of \fIn\fR. .TP @@ -135,6 +138,10 @@ Use Euclidean division (default). Use truncating division (same as C). \fIa\fR / \fIb\fR is rounded towards zero. \fIa\fR % \fIb\fR can be negative. +.TP +\fL\'\fR 1 +Enable numbering bits (disable with 0). +If the base is a power of two, print the number of the corresponding bit above each digit. .SH SOURCE .B /sys/src/cmd/pc.y .SH "SEE ALSO" diff --git a/sys/src/cmd/pc.y b/sys/src/cmd/pc.y index e7eafad79..d6db26bba 100644 --- a/sys/src/cmd/pc.y +++ b/sys/src/cmd/pc.y @@ -7,7 +7,7 @@ #include #include -int inbase = 10, outbase, divmode, sep, fail, prompt; +int inbase = 10, outbase, divmode, sep, heads, fail, prompt; enum { MAXARGS = 16 }; typedef struct Num Num; @@ -228,11 +228,38 @@ getsym(char *n, int mk) return *p; } +static void +printhead(int n, int s, int sp, char *t) +{ + char *q; + int i, j, k; + + for(i = 1; i < n; i *= 10) + ; + while(i /= 10, i != 0){ + q = t; + *--q = 0; + for(j = 0, k = 0; j < n; j += s, k++){ + if(k == sep && sep != 0){ + *--q = ' '; + k = 0; + } + if(j >= i || j == 0 && i == 1) + *--q = '0' + j / i % 10; + else + *--q = ' '; + } + for(j = 0; j < sp; j++) + *--q = ' '; + print("%s\n", q); + } +} + void numprint(Num *n) { int b; - int l, i; + int l, i, st, sp; char *s, *t, *p, *q; if(n == nil) return; @@ -246,6 +273,18 @@ numprint(Num *n) l = strlen(s); t = emalloc(l * 2 + 4); q = t + l * 2 + 4; + if(heads){ + switch(b){ + case 16: st = 4; sp = 2; break; + case 8: st = 3; sp = 1; break; + case 2: st = 1; sp = 2; break; + default: st = 0; sp = 0; + } + if(n->sign < 0) + sp++; + if(st != 0) + printhead(mpsignif(n), st, sp, q); + } *--q = 0; for(p = s + l - 1, i = 0; p >= s && *p != '-'; p--, i++){ if(sep != 0 && i == sep){ @@ -409,6 +448,19 @@ stat: { last = nil; } numdecref(last); last = nil; } + | '\'' { save = inbase; inbase = 10; } expr { + inbase = save; + save = heads; + if(!fail) + heads = mptoi($3); + if(heads != 0 && heads != 1){ + error("no."); + heads = save; + } + numdecref($3); + numdecref(last); + last = nil; + } | error expr: LNUM @@ -638,6 +690,30 @@ fnbin(int, Num **a) return r; } +Num * +fnpb(int, Num **a) +{ + Num *r; + int b; + + if(toint(a[1], &b, 1)){ + out: + numdecref(a[0]); + numdecref(a[1]); + return nil; + } + if(b != 0 && b != 2 && b != 8 && b != 10 && b != 16){ + error("unsupported base"); + goto out; + } + r = nummod(a[0]); + if(b == 0) + r->b = 0; + else + r->b = STRONG | b; + return r; +} + Num * fnabs(int, Num **a) { @@ -903,6 +979,7 @@ main(int argc, char **argv) regfunc("dec", fndec, 1); regfunc("oct", fnoct, 1); regfunc("bin", fnbin, 1); + regfunc("pb", fnpb, 2); regfunc("abs", fnabs, 1); regfunc("round", fnround, 2); regfunc("floor", fnfloor, 2);