summaryrefslogtreecommitdiff
path: root/libinterp/ipint.c
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2008-01-16 01:19:38 +0000
committerCharles.Forsyth <devnull@localhost>2008-01-16 01:19:38 +0000
commitca1042d3d05e5e9b2b5094b04197c96ec3b34bfe (patch)
tree6a2cb733509e5a3692efa952e1c3bc5503c25355 /libinterp/ipint.c
parente84ac69296d2bd901d9d5dba59a1873fc6fb7cc1 (diff)
20080116-0125
Diffstat (limited to 'libinterp/ipint.c')
-rw-r--r--libinterp/ipint.c91
1 files changed, 79 insertions, 12 deletions
diff --git a/libinterp/ipint.c b/libinterp/ipint.c
index b7cb8af2..d81fccf4 100644
--- a/libinterp/ipint.c
+++ b/libinterp/ipint.c
@@ -46,6 +46,44 @@ freeIPint(Heap *h, int swept)
}
void
+IPint_iptob64z(void *fp)
+{
+ F_IPint_iptob64 *f;
+ BigInt b;
+ char buf[MaxBigBytes]; /* TO DO: should allocate these */
+ uchar *p;
+ int n, o;
+
+ f = fp;
+ destroy(*f->ret);
+ *f->ret = H;
+
+ if(f->i == H)
+ error(exNilref);
+
+ b = MP(f->i);
+ n = (b->top+1)*Dbytes;
+ p = malloc(n+1);
+ if(p == nil)
+ error(exHeap);
+ n = mptobe(b, p+1, n, nil);
+ if(n < 0){
+ free(p);
+ return;
+ }
+ p[0] = 0;
+ if(n != 0 && (p[1]&0x80)){
+ /* force leading 0 byte for compatibility with older representation */
+ o = 0;
+ n++;
+ }else
+ o = 1;
+ enc64(buf, sizeof(buf), p+o, n);
+ retstr(buf, f->ret);
+ free(p);
+}
+
+void
IPint_iptob64(void *fp)
{
F_IPint_iptob64 *f;
@@ -112,21 +150,33 @@ IPint_iptostr(void *fp)
retstr(buf, f->ret);
}
+static Keyring_IPint*
+strtoipint(String *s, int base)
+{
+ char *p, *q;
+ BigInt b;
+
+ p = string2c(s);
+ b = strtomp(p, &q, base, nil);
+ if(b == nil)
+ return H;
+ if(q == p || *q != 0){
+ mpfree(b);
+ return H;
+ }
+ return newIPint(b);
+}
+
void
IPint_b64toip(void *fp)
{
F_IPint_b64toip *f;
- BigInt b;
f = fp;
destroy(*f->ret);
*f->ret = H;
- if(f->str == H)
- error(exNilref);
-
- b = strtomp(string2c(f->str), nil, 64, nil);
- *f->ret = newIPint(b);
+ *f->ret = strtoipint(f->str, 64);
}
void
@@ -167,17 +217,12 @@ void
IPint_strtoip(void *fp)
{
F_IPint_strtoip *f;
- BigInt b;
f = fp;
destroy(*f->ret);
*f->ret = H;
- if(f->str == H)
- return;
-
- b = strtomp(string2c(f->str), nil, f->base, nil);
- *f->ret = newIPint(b);
+ *f->ret = strtoipint(f->str, f->base);
}
/* create a random integer */
@@ -384,6 +429,27 @@ IPint_div(void *fp)
f->ret->t1 = newIPint(rem);
}
void
+IPint_mod(void *fp)
+{
+ F_IPint_mod *f;
+ BigInt i1, i2, ret;
+
+ f = fp;
+ destroy(*f->ret);
+ *f->ret = H;
+
+ if(f->i1 == H || f->i2 == H)
+ error(exNilref);
+
+ i1 = ((IPint*)f->i1)->b;
+ i2 = ((IPint*)f->i2)->b;
+ ret = mpnew(0);
+ if(ret != nil)
+ mpmod(i1, i2, ret);
+
+ *f->ret = newIPint(ret);
+}
+void
IPint_neg(void *fp)
{
F_IPint_neg *f;
@@ -669,6 +735,7 @@ if(0)print("1");
two = itomp(2, nil);
if(mpcmp(diff, two) < 0){
+ mpfree(one);
mpfree(two);
itomp(0, result);
return;