X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=sys%2Fsrc%2Fcmd%2Fpc.y;h=7592f578bf32a229a61dd43e315c6773a9673bf0;hb=6e6beff85d3f2d71c4e1d92d1f2091d01c7d5c34;hp=d6db26bbaa56fe3adced0f55f7baa59b1cc7122e;hpb=f5fcb42cffce91e8142c6934e398c11c95e907ec;p=plan9front.git diff --git a/sys/src/cmd/pc.y b/sys/src/cmd/pc.y index d6db26bba..7592f578b 100644 --- a/sys/src/cmd/pc.y +++ b/sys/src/cmd/pc.y @@ -55,7 +55,7 @@ numalloc(void) r = emalloc(sizeof(Num)); r->ref = 1; - r->p = emalloc(0); + r->p = emalloc(sizeof(mpdigit)); mpassign(mpzero, r); return r; } @@ -195,6 +195,10 @@ numbin(int op, Num *a, Num *b) else mpassign(b, a); break; + case '$': + a->b = b->b; + mpxtend(b, mptoi(a), a); + break; } numdecref(b); return a; @@ -299,7 +303,7 @@ numprint(Num *n) if(mpcmp(n, mpzero) != 0) switch(b){ case 16: *--q = 'x'; *--q = '0'; break; - case 10: if(outbase != 0 && outbase != 10) {*--q = 'd'; *--q = '0';} break; + case 10: if(outbase != 0 && outbase != 10 || inbase != 10) {*--q = 'd'; *--q = '0';} break; case 8: *--q = '0'; break; case 2: *--q = 'b'; *--q = '0'; break; } @@ -310,15 +314,28 @@ numprint(Num *n) free(t); } +void +numdecrefs(int n, Num **x) +{ + int i; + + for(i = 0; i < n; i++) + numdecref(x[i]); +} + Num * fncall(Symbol *s, int n, Num **x) { int i; - if(s->t != SYMFUNC) + if(s->t != SYMFUNC){ + numdecrefs(n, x); return error("%s: not a function", s->name); - else if(s->nargs >= 0 && s->nargs != n) + } + else if(s->nargs >= 0 && s->nargs != n){ + numdecrefs(n, x); return error("%s: wrong number of arguments", s->name); + } for(i = 0; i < n; i++) if(x[i] == nil) return nil; @@ -376,6 +393,7 @@ hexfix(Symbol *s) %left unary %left '*' '/' '%' %right LOEXP +%right '$' %{ int save; @@ -488,6 +506,7 @@ expr: LNUM | '-' expr %prec unary { $$ = nummod($2); if($$ != nil) mpsub(mpzero, $$, $$); } | '~' expr %prec unary { $$ = nummod($2); if($$ != nil) mpnot($$, $$); } | '!' expr %prec unary { $$ = nummod($2); if($$ != nil) {itomp(mpcmp($$, mpzero) == 0, $$); $$->b = 0; } } + | '$' expr { $$ = nummod($2); if($$ != nil) if($2->sign > 0) mpxtend($2, mpsignif($2), $$); else mpassign($2, $$); } | expr '?' expr ':' expr %prec '?' { if($1 == nil || mpcmp($1, mpzero) != 0){ $$ = $3; @@ -528,6 +547,7 @@ expr: LNUM if($$ == nil) error("no last result"); else numincref($$); } + | expr '$' expr { $$ = numbin('$', $1, $3); } elist: { $$.n = 0; } | elist1 elist1: expr { $$.x[0] = $1; $$.n = 1; } @@ -819,6 +839,39 @@ fnxtend(int, Num **a) return a[0]; } +Num * +fnclog(int n, Num **a) +{ + int r; + + if(n != 1 && n != 2){ + numdecrefs(n, a); + return error("clog: wrong number of arguments"); + } + if(mpcmp(a[0], mpzero) <= 0 || n == 2 && mpcmp(a[1], mpone) <= 0){ + numdecref(a[0]); + return error("invalid argument"); + } + if(n == 1 || mpcmp(a[1], mptwo) == 0){ + a[0] = nummod(a[0]); + mpsub(a[0], mpone, a[0]); + itomp(mpsignif(a[0]), a[0]); + a[0]->b = 0; + if(n == 2) numdecref(a[1]); + return a[0]; + } + a[0] = nummod(a[0]); + for(r = 0; mpcmp(a[0], mpone) > 0; r++){ + mpadd(a[0], a[1], a[0]); + mpsub(a[0], mpone, a[0]); + mpdiv(a[0], a[1], a[0], nil); + } + itomp(r, a[0]); + a[0]->b = 0; + numdecref(a[1]); + return a[0]; +} + Num * fnubits(int, Num **a) { @@ -986,6 +1039,7 @@ main(int argc, char **argv) regfunc("ceil", fnceil, 2); regfunc("trunc", fntrunc, 2); regfunc("xtend", fnxtend, 2); + regfunc("clog", fnclog, -1); regfunc("ubits", fnubits, 1); regfunc("sbits", fnsbits, 1); regfunc("nsa", fnnsa, 1);