]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/cmd/pc.y
cc, ?[acl]: fix gethunk() and move common memory allocator code to cc/compat
[plan9front.git] / sys / src / cmd / pc.y
index 910880ee77afafb55509e3745af42d67456a5e0f..6d828f8a2c5a2be8b0881fa0fb0254b42894c6b8 100644 (file)
@@ -7,7 +7,7 @@
 #include <thread.h>
 #include <libsec.h>
 
-int inbase = 10, outbase, divmode, sep, fail, prompt;
+int inbase = 10, outbase, divmode, sep, heads, fail, prompt;
 enum { MAXARGS = 16 };
 
 typedef struct Num Num;
@@ -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;
@@ -228,11 +232,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 +277,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){
@@ -260,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;
                }
@@ -271,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;
@@ -337,6 +393,7 @@ hexfix(Symbol *s)
 %left unary
 %left '*' '/' '%'
 %right LOEXP
+%right '$'
 
 %{
        int save;
@@ -409,6 +466,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
@@ -436,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;
@@ -476,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; }
@@ -527,7 +599,7 @@ yylex(void)
        if(c == '\n') prompted = 0;
        if(isdigit(c)){
                for(p = buf, *p++ = c; c = Bgetc(in), isalnum(c) || c == '_'; )
-                       if(p < buf + sizeof(buf) - 1)
+                       if(p < buf + sizeof(buf) - 1 && c != '_')
                                *p++ = c;
                *p = 0;
                Bungetc(in);
@@ -638,6 +710,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)
 {
@@ -729,6 +825,7 @@ fntrunc(int, Num **a)
                numdecref(a[1]);
                return nil;
        }
+       a[0] = nummod(a[0]);
        mptrunc(a[0], i, a[0]);
        return a[0];
 }
@@ -739,10 +836,44 @@ fnxtend(int, Num **a)
        int i;
        
        if(toint(a[1], &i, 1)) return nil;
+       a[0] = nummod(a[0]);
        mpxtend(a[0], i, a[0]);
        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)
 {
@@ -766,6 +897,28 @@ fnsbits(int, Num **a)
        return a[0];
 }
 
+Num *
+fnnsa(int, Num **a)
+{
+       int n, i;
+       mpdigit d;
+
+       a[0] = nummod(a[0]);
+       if(a[0]->sign < 0){
+               numdecref(a[0]);
+               return error("invalid argument");
+       }
+       n = 0;
+       for(i = 0; i < a[0]->top; i++){
+               d = a[0]->p[i];
+               for(; d != 0; d &= d-1)
+                       n++;
+       }
+       itomp(n, a[0]);
+       a[0]->b = 0;
+       return a[0];
+}
+
 Num *
 fngcd(int, Num **a)
 {
@@ -881,14 +1034,17 @@ 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);
        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);
        regfunc("gcd", fngcd, 2);
        regfunc("minv", fnminv, 2);
        regfunc("rand", fnrand, 1);