OpenBSD bc

From Rosetta Code
OpenBSD bc is an implementation of bc. Other implementations of bc.

This is the /usr/bin/bc on OpenBSD systems. It has some, but not all, of the features as GNU bc.

These extensions are in OpenBSD bc but not in POSIX:

  • Two new options, bc -c and bc -e.
  • Long names (more than one letter) for variables and functions.
  • # Line comments.
  • Relational operators (== <= >= !- < >) in any expression, not only in 'if', 'while' or 'for'.
  • Boolean operators (! && ||).
  • else branch of an 'if' statement.
  • print statement, with escapes like '\n'.
  • Special variable last, also known as . (a single dot).

The most unique feature of OpenBSD bc is that it runs on top of dc. (The original AT&T bc also did this, but GNU bc does not.) OpenBSD bc translates the entire program from bc to dc, then calls OpenBSD dc /usr/bin/dc to run the program. (OpenBSD dc has several extensions to allow this to work.)

The bc -c option just skips the second step, so we can see how OpenBSD translates a program from bc to dc. Here follows an example with the Fibonacci sequence.

  • Program using bc
    $ cat prog.bc
    # compute fib[0] thru fib[19]
    fib[0] = 0
    fib[1] = 1
    for (i = 2; i < 20; i++) {
    fib[i] = fib[i - 1] + fib[i - 2]
    }
     
    # print fib[a] thru fib[b]
    define fib(a, b) {
    auto i
    print "fib ", a, "..", b, " = "
    for (i = a; i <= b; i++) {
    print fib[i]
    if (i < b) print ", " else print "\n"
    }
    }
     
    # assignments to prevent printing of trash
    trash = fib(0, 4)
    trash = fib(15, 19)
    quit
  • Translation to dc
    $ bc -c prog.bc | vis
     
    0 0:\M^?\^A\^A
    1 1:\M^?\^A\^A
    [li 1-;\M^?\^A\^Ali 2-;\M^?\^A\^A+li:\M^?\^A\^Alid1+sis.li 20>0]s0
    2dsis.li 20>0
     
     
    [[, ]n]s1
    [[
    ]n]s2
    [li;\M^?\^A\^Ads.nlilb>1e2 lid1+sis.lilb!<0]s0
    [0SiSbSa[fib ]nlads.n[..]nlbds.n[ = ]nladsis.lilb!<0 Las.Lbs.Lis.0 1Q]s\M^?\^A\^B
     
     
     
     
    0 4l\M^?\^A\^Bxs\M^?\^A\^C
    15 19l\M^?\^A\^Bxs\M^?\^A\^C
    q
  • Output
    $ bc -c prog.bc | dc -x  # or simply $ bc prog.bc
    fib 0..4 = 0, 1, 1, 2, 3
    fib 15..19 = 610, 987, 1597, 2584, 4181