On Mon, 29 Jan 2007, Otto Moerbeek wrote:

> On Mon, 29 Jan 2007, Otto Moerbeek wrote:
> 
> > On Mon, 29 Jan 2007, Karel Kulhavy wrote:
> > 
> > > I just found three bugs in the OpenBSD 4.0 "bc" program.
> > 
> > 
> > All three bugs seem to related to the use of a non-decimal input base
> > in combination with using the -l lib. 
> > 
> > This is because the stored routines interpret the number according to
> > the base at execution time.
> > Shows what is going on. I have to think a bit on how to solve it and
> > what (id) SU says anything about this.
> > 
> > $ bc
> > define d(x) {
> >   return x + 1.1;
> > }
> > d(0)
> > 1.1
> > ibase=2
> > d(0)
> > 1.5
> 
> SU does not say anthing explicit about this on first read. In the
> meantime I checked Solaris and the original AT&T bc/dc. They both
> produce the same results as above. So the behaviour might be
> surprising, but it is historically consistent. 
> 
> Strange is that your 0) test does work OK on Solaris. Some more
> investigation to be done...

It turns out the -l functions in Solaris save/restore the input base.

The diff below fixes it for l().  Note that some of your tests still
produce strange results, but that is due to weird handling of
non-decimal fractions wrt scale:

For example, with ibase=11
0.1 produces 0.0
0.10 produces .09
0.100 produces 0.090

As far as I remember, this is consistent behaviour compared to
historic versions of bc. 

        -Otto

Index: bc.library
===================================================================
RCS file: /cvs/src/usr.bin/bc/bc.library,v
retrieving revision 1.1
diff -u -p -r1.1 bc.library
--- bc.library  25 Sep 2003 19:34:22 -0000      1.1
+++ bc.library  29 Jan 2007 09:36:41 -0000
@@ -80,8 +80,14 @@ define e(x){
 }
 
 define l(x){
-       auto a, b, c, d, e, f, g, u, s, t
-       if(x <=0) return(1-10^scale)
+       auto a, b, c, d, e, f, g, u, s, t, r
+       r = ibase;
+       ibase = A;
+       if(x <= 0) {
+         a = 1-10^scale;
+         ibase = r;
+         return(a)
+       }
        t = scale
 
        f=1
@@ -116,6 +122,7 @@ define l(x){
                g=c/d
                if(g==e){
                        scale = t
+                       ibase = r;
                        return(u*c/d)
                }
                e=g

Reply via email to