]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/cmd/pc.y
delete old NOTICE file
[plan9front.git] / sys / src / cmd / pc.y
index d6db26bbaa56fe3adced0f55f7baa59b1cc7122e..7592f578bf32a229a61dd43e315c6773a9673bf0 100644 (file)
@@ -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);