=================================================================== RCS file: /cvsrepo/anoncvs/cvs/src/usr.bin/dc/bcode.c,v retrieving revision 1.44 retrieving revision 1.45 diff -u -r1.44 -r1.45 --- src/usr.bin/dc/bcode.c 2012/11/06 16:00:05 1.44 +++ src/usr.bin/dc/bcode.c 2012/11/07 11:06:14 1.45 @@ -1,4 +1,4 @@ -/* $OpenBSD: bcode.c,v 1.44 2012/11/06 16:00:05 otto Exp $ */ +/* $OpenBSD: bcode.c,v 1.45 2012/11/07 11:06:14 otto Exp $ */ /* * Copyright (c) 2003, Otto Moerbeek @@ -257,6 +257,12 @@ (void)signal(SIGINT, sighandler); } +u_int +bmachine_scale(void) +{ + return bmachine.scale; +} + /* Reset the things needed before processing a (new) file */ void reset_bmachine(struct source *src) @@ -991,7 +997,7 @@ } void -bmul_number(struct number *r, struct number *a, struct number *b) +bmul_number(struct number *r, struct number *a, struct number *b, u_int scale) { BN_CTX *ctx; @@ -1005,11 +1011,9 @@ bn_check(BN_mul(r->number, a->number, b->number, ctx)); BN_CTX_free(ctx); - if (rscale > bmachine.scale && rscale > ascale && rscale > bscale) { - r->scale = rscale; - normalize(r, max(bmachine.scale, max(ascale, bscale))); - } else - r->scale = rscale; + r->scale = rscale; + if (rscale > bmachine.scale && rscale > ascale && rscale > bscale) + normalize(r, max(scale, max(ascale, bscale))); } static void @@ -1029,7 +1033,7 @@ } r = new_number(); - bmul_number(r, a, b); + bmul_number(r, a, b, bmachine.scale); push_number(r); free_number(a); @@ -1160,7 +1164,7 @@ struct number *a, *p; struct number *r; bool neg; - u_int scale; + u_int rscale; p = pop_number(); if (p == NULL) { @@ -1191,7 +1195,7 @@ if (BN_is_negative(p->number)) { neg = true; negate(p); - scale = bmachine.scale; + rscale = bmachine.scale; } else { /* Posix bc says min(a.scale * b, max(a.scale, scale) */ u_long b; @@ -1199,30 +1203,37 @@ b = BN_get_word(p->number); m = max(a->scale, bmachine.scale); - scale = a->scale * (u_int)b; - if (scale > m || (a->scale > 0 && (b == BN_MASK2 || + rscale = a->scale * (u_int)b; + if (rscale > m || (a->scale > 0 && (b == BN_MASK2 || b > UINT_MAX))) - scale = m; + rscale = m; } if (BN_is_zero(p->number)) { r = new_number(); bn_check(BN_one(r->number)); - normalize(r, scale); + normalize(r, rscale); } else { + u_int ascale, mscale; + + ascale = a->scale; while (!BN_is_bit_set(p->number, 0)) { - bmul_number(a, a, a); + ascale *= 2; + bmul_number(a, a, a, ascale); bn_check(BN_rshift1(p->number, p->number)); } r = dup_number(a); - normalize(r, scale); bn_check(BN_rshift1(p->number, p->number)); + mscale = ascale; while (!BN_is_zero(p->number)) { - bmul_number(a, a, a); - if (BN_is_bit_set(p->number, 0)) - bmul_number(r, r, a); + ascale *= 2; + bmul_number(a, a, a, ascale); + if (BN_is_bit_set(p->number, 0)) { + mscale += ascale; + bmul_number(r, r, a, mscale); + } bn_check(BN_rshift1(p->number, p->number)); } @@ -1235,8 +1246,7 @@ bn_check(BN_one(one)); ctx = BN_CTX_new(); bn_checkp(ctx); - scale_number(one, r->scale + scale); - normalize(r, scale); + scale_number(one, r->scale + rscale); if (BN_is_zero(r->number)) warnx("divide by zero"); @@ -1245,8 +1255,9 @@ r->number, ctx)); BN_free(one); BN_CTX_free(ctx); + r->scale = rscale; } else - normalize(r, scale); + normalize(r, rscale); } push_number(r); free_number(a);