HP-67
NAME
hp67 - a scientific calculator in Reverse Polish
Notation
SYNOPSIS
hp67 [-n|--noexit] [--program=program|-p program]
[--ignorercfile|-i] [--help|-h]
DESCRIPTION
This program emulates an HP-67 calculator with a few minor
variations. This calculator uses the 'Reverse Polish Notation'
favoured by Hewlett-Packard.
Reverse Polish Notation is somewhat different from the
"forward" notation available on many, probably most, handheld
calculators. It is the notation used by the Forth system of
languages. Here are some examples of how the notation
works:
To evaluate: (3 + 4*7) / (2 + 8^3)
You hit the following sequence of keys:
-
3 <ENTER>
4 <ENTER>
7 *
+
2 <ENTER>
8 <ENTER>
3 y^x
+
/
The <ENTER> key is used to separate different numbers
entered consecutively. As numbers are entered they are pushed
onto a LIFO stack. The most recently entered number, at the top
of the stack, is called the 'X' value, the next most recently
entered number is the 'Y' value. On the screen the 'X' appears
nearest the bottom, with 'Y' immediately above it. Unary
operations such as 'sin' pop a single number (X) off the stack,
act on that number, and push the result onto the stack. Binary
operations such as '/' pop two numbers off the stack, and
divide the first number popped (X) into the second (Y), then
push the result onto the stack. This has the effect of reducing
by one the total number of elements on the stack. Look over the
above example until it's clear. Another register, 'LSTX', is
not displayed on the stack. This holds the value which 'X' held
before the last operation was made. Not all operations will
update this number. LSTX is most commonly used in error
correction, such as if you typed '*' instead of '/', and in the
implementation of automatic constants.
OPTIONS
- -n, --noexit
- Disable the CTRL-D exit key. This behaviour is desirable
if the program is run from within a dedicated xterm, such as
via the following shell script:
-
#! /bin/sh #
/usr/X11R6/bin/color_xterm $@ -ls -tn xterm-color \ -e
hp67 --noexit &
- This script can then be invoked, for instance, as
follows:
- hp67.sh -iconic -geometry +700+400
- to produce a dedicated xterm window which cannot be
aborted, short of sending the program a killing signal.
- -p program, --program=program
- Load the program space with the named program during.
Equivalent to issuing the command r/prog program from
the keyboard immediately when the program begins.
- -i, --ignorercfile
- Don't preload any programs.
- -h, --help
- Issue a usage message and exit.
SPECIFICS OF THE HP-67 EMULATOR
Command entry format
Numbers must be entered alone on the line. They may be
expressed in fixed or scientific notation. Examples of valid
entries on the command line are:
- 12.493 12.4e-5 .008E4 1.2E+4
Note that it is not normally possible to enter negative
numbers directly at the command line prompt (but see the entry
for '{' in the section on "magic" keys in curses mode.)
Commands and operations may be entered alone on the command
line, or immediately after a valid number, with argument if
allowed. The argument must be separated from the command by one
or more blanks or tab characters. Examples of valid commands
and operations are:
-
+
sto speedoflight
dsp 9
fix
See the list of operations for details of which commands
require operands.
If an operation pops a non-existent stack element, it is not
an error, a zero is obtained. Similarly, an attempt to read an
uninitialized memory element returns a zero.
Display layout
The calculator requires at least an 80x22 screen to work,
and the layout of buttons is most logical when the number of
columns is exactly 80. The upper portion of the screen consists
of buttons showing the currently valid commands to the
calculator. The right side has a numeric keypad, while the
lower-left portion is responsible for interaction with the
user. The lower-middle portion shows the most recently accessed
memory elements, up to 15 if the number of screen rows is large
enough, and the first 8 characters of the element's label
(assuming an 80 column screen).
In immediate (interactive) mode, a number of stack elements
are displayed in this region, with X at the bottom, Y above it,
and higher elements above those.
In program mode, the current insertion and run point is
shown with an arrow to its left. Above and below it are
neighbouring program elements. New elements are inserted after
the position of the arrow, and when the calculator runs, the
arrow always shows the next step which will be executed.
A stepping mode also exists. If a program is interrupted
with a keypress, or if "step" is entered in immediate mode,
then the display shows part of the stack, and part of the
program. The program window shows the next step which will be
performed, the earlier step in the program memory (not
necessarily the last step performed, if that was a branch), and
the step after the next one to be performed. Every time "step"
is entered, one program step is executed and the insertion/run
pointer is updated.
Curses magic behaviour
When operating in curses mode, hp67 performs some extra
actions for certain input sequences.
The '#' is a comment character for almost all functions. The
disk I/O functions ignore it, and so can load file names
containing the character, but all other operations consider
that the argument ends with the last non-whitespace before the
'#' character appears. A comment may not be the only content of
the input line.
If a line of input begins with a character which identifies
it as a number, such as a digit or decimal point, then it
continues to accept characters until such time as one shows up
which is not part of a valid float. The valid float is passed
to the interpreter, while the remaining text waits on the input
line. So, if the sequence "102s" is typed, it is as if the
number "102", then <ENTER>, then "s" were typed. If the
sequence "45e+l" is entered, it is interpreted as "45",
<ENTER>, "e+l". Note that there is at present no command
which begins "e+l", so this is likely not to appear in normal
use. If the sequence "1e4e" is typed, it is interpreted as
"1e4" (10000), <ENTER>, "e". This number watching allows
one to avoid an extra keypress, it is legal to type "30 ENTER
40 +", the result is seventy.
Note that the following sequence on the command line: "3+4"
<ENTER> may not do what you expect. This has the effect
of pushing 3 onto the stack, adding it to whatever was on the
stack before, then pusing 4 onto the stack.
Now, the input line supports a few special command
sequences.
In the following, the notation "M-a" means "meta (lowercase)
a". This sequence can be produced by holding down the ALT key
on terminals which support this, or prefixing the 'a' keypress
with ESC.
The following are 'hot keys'. If they are entered in the
first position on a blank input line their functions will be
invoked:
- <DELETE>
- In immediate mode, invokes the "clx" function to delete
the top element of the stack. In program mode, deletes the
current program line.
- M-<SPACE>
- In immediate mode, invokes the "step" function.
- M-<key>
- If <key> is a printable key, in immediate mode this
invokes the command "run <key>", running a subroutine
identified by the single letter label <key>. In program
mode, this invokes the command "label <key>", creating
an entry point identified by the single letter label
<key>.
- <CTRL>-D
- In immediate mode, exits the calculator. In program mode,
returns to immediate mode.
- UP-ARROW
- In program mode, moves the program insertion/execution
pointer back one space.
- DOWN-ARROW
- In program mode, moves the program insertion/execution
pointer forward one space (without executing the step).
- {
- As the first element on the line, the '{' character
disables (for the current input line) the magic
floating-point number parsing described above. This is
intended for future expansion, when input types such as
complex numbers may use different characters to mark input.
It can be used to enter negative numbers at the command
line.
- CTRL-L
- forces curses to redraw the entire window from scratch.
Useful if the window is resized, or if some other output to
the screen intrudes.
All control keys not listed above are filtered at the
keyboard read stage and can never be embedded into labels or
commands. The TAB key is immediately translated into a blank at
read time.
On terminals which support ncurses mouse events, the
function list at the top of the screen, and the keypad on the
right side, are both clickable to invoke the corresponding
action. Commands which take no arguments are sent with an
implied <ENTER> following them, so simply pressing the
text of "sin" calculates the sine of the current X value.
Commands which take arguments are sent with an implied BLANK
following them, allowing the user to enter the argument.
Numbers on the keypad, of course, are sent without
modification.
LIST OF COMMANDS
The following commands are available either in programming
or in user mode:
- + --'Addition operator X <- Y + X LSTX
- This operator takes no arguments. It pops the top two
elements of the stack and adds them together, pushing the
result on the stack.
- - --'Subtraction operator X <- Y - X LSTX
- As above, but it subtracts.
- * --'Multiplication operator X <- Y * X LSTX
- As above, but it multiplies.
- / --'Division operator X <- Y / X LSTX
- ! --'Factorial operator X <- !X LSTX
- This operator takes no arguments. It replaces the value
in the X register with the factorial of the number. The
factorial is the product of all natural numbers less than or
equal to the number. If the value in X is not an integer, it
returns the real-number generalization of the factorial, the
gamma function of 'X+1'. An error occurs if X is a negative
integer, or if an overflow occurs.
- recip --'Reciprocal operator X <- 1 / X LSTX
- This operator takes no arguments. It replaces the value
in the X register with its reciprocal.
- chs --'Change sign operator X <- -X LSTX
- This operator takes no arguments. It replaces the value
in the X register with its negative value.
- sin --'Sine operator X <- sin(X) LSTX
- This operator takes no arguments. It repalces the value
in the X register with its sine, where X is interpreted as an
angle in the units of the 'THETA' flag. See below for
information on changing this flag.
- cos --'Cosine operator X <- cos(X) LSTX
- As above, but for cosine.
- tan --'Tangent operator X <- tan(X) LSTX
- As above, but for tangent.
- asin --'Inverse sine operator X <- asin(X) LSTX
- As above, but for inverse sine.
- acos --'Inverse cosine operator X <- acos(X) LSTX
- As above, but for inverse cosine.
- atan --'Inverse tangent operator X <- atan(X)
LSTX
- As above, but for inverse tangent.
- sqrt --'Square root operator X <- sqrt(X) LSTX
- This operator takes no arguments. It replaces the value
in the X register with its square root. This won't work for
negative numbers.
- square --'Square operator X <- X ^ 2 LSTX
- This operator takes no arguments. It replaces the value
in the X register with its square.
- ln --'Natural logarithm operator X <- ln(X) LSTX
- This operator takes no arguments. It replaces the value
in the X register with its natural logarithm.
- exp --'Exponential operator X <- exp(X) LSTX
- This operator takes no arguments. It replaces the value
in the X register with e^X.
- log10 --'Base 10 logarithm X <- log(X) LSTX
- This operator takes no arguments. It replaces the value
in the X register with its base 10 logarithm.
- exp10 --'Power on 10 operator X <- 10^X LSTX
- This operator takes no arguments. It replaces the value
in the X register with 10^X.
- y^x --'Power operator X <- Y ^ X LSTX
- This operator takes no arguments. It replaces the value
in the X register with the value Y^X. This returns errors if
X is negative and Y is not an integer, or if X is zero and Y
is less than or equal to zero.
- abs --'Absolute value operator X <- abs(X) LSTX
- This operator takes no arguments. It replaces the value
in the X register with its absolute value.
- dsp --'Set display precision
- This operator takes one argument, an integer between 0
and 14 inclusive. In 'fix' and 'sci' modes this sets the
number of digits to appear to the right of the decimal point.
In 'eng' mode this sets the total number of digits to appear
on the screen to 'n+1'. In other words, changing from 'sci'
to 'eng' mode does not change the precision of the display.
This operator is available with indirection. If the argument
is "(i)" it will set the number of digits to the greatest
integer value of the I register, if that value lies in the
correct range.
- fix --'Set fixed display mode
- This operator takes no arguments. It sets the display of
stack elements to fixed point notation. Numbers which cannot
be displayed in this notation in the precision specified by
'dsp' will be displayed instead in scientific notation.
- sci --'Set scientific notation display mode
- This operator takes no arguments. It sets the display of
stack elements to scientific notation. In this form all
numbers are written with a single digit preceding the decimal
point, and a four digit exponent on the right of the
display.
- eng --'Set engineering notation display mode
- As above, but between one and three digits precede the
decimal point, and the exponent is always a multiple of
three.
- hex --'Set hexadecimal display mode
- In hexadecimal mode, all numbers are displayed in
hexadecimal format, as the next integer closer to zero (i.e.
rounding down for positive values, and up for negative
values). In hexadecimal mode the magic input completion is
disabled, and numbers can be entered as either octal,
decimal, or hexadecimal integers. A number beginning with
'0x' is interpreted as hexadecimal, otherwise a number
beginning with '0' is octal. In all other cases the number is
treated as a decimal value.
- deg --'Set degrees mode THETA = degrees
- This operator takes no arguments. It sets the internal
'THETA' flag to degrees. All subsequent angles are
interpreted in units of degrees, and functions which return
angles return them in degrees.
- rad --'Set radians mode THETA = radians
- As above, but it sets angles to radians.
- grd --'Set gradians mode THETA = gradians
- As above, but it sets angles to gradians. There are 400
gradians in a circle, and if you use this mode even once I'll
be surprised.
- sto --'Store to memory register <label> <-
X
- This operator takes a single argument. That argument can
be any string which does not contain a '#' and does not begin
with a '.'. The current X value will be written into the
memory identified by this label. If no such memory register
exists, it is created. This operator can also use indirect
addressing. If the label is "(i)", the current value of the I
register is extracted, converted to an integer, then to a
character string, and passed as if it were the argument typed
on the command line. So, if I holds the value 214.1, the X
register is stored to the memory element labelled "214".
- rcl --'Recall from memory reg. X <- <label>
- As above, but it recalls from memory and pushes the
number obtained onto the stack. The current X value is not
lost, it is merely pushed up with the rest of the stack.
- sto+ --'Add to memory register <label> <-
<label>+X
- This operator takes one argument, the memory label. It
acts like the register, it adds the current X value to it.
This operation is available with indirection.
- sto- --'Subtract from memory reg. <label> <-
<label>-X
- As above, but it subtracts X from the memory
register.
- sto* --'Multiply into memory reg. <label> <-
<label>*X
- As above, but it multiplies X into the memory
register.
- sto/ --'Divide into memory reg. <label> <-
<label>/X
- As above, but it divides X into the memory register.
- x<>y --'Swap X and Y X <--> Y
- This operator takes no arguments. It exchanges the X and
Y elements on the stack. This is useful, for instance, if you
want to evaluate X^Y. You can first swap X and Y, then use
the 'pow' operator.
- r>p --'Rectangular to polar conversion LSTX
-
This operator takes no arguments. It converts the pair
(X,Y) into polar form.
-
X <- sqrt(X^2 + Y^2)
Y <- atan2(Y,X)
- p>r --'Polar to rectangular conversion LSTX
-
This operator takes no arguments. It reads the X register
as a distance and the Y register as an angle, and converts
to cartesian form. This has the effect:
-
X <- X * cos(Y)
Y <- X * sin(Y)
- The former Y value is lost.
- d>r --'Degrees to radians conv. X <- X * 180/pi
LSTX
- This operator takes no arguments. It converts the value
in the X register from degrees to radians. Note that it does
not change the value of the 'angmode' internal flag.
- r>d --'Radians to degrees X <- X * 180/pi LSTX
- This operator takes no arguments. It converts the value
in the X register from an angle in radians to one in degrees.
Note that it does not change the value of the internal
'THETA' flag.
- pi --'Numerical value of pi X <- pi
- This operator takes no arguments. It is shorthand for
entering the first 19 decimal places of 'pi'. It pushes 'pi'
onto the stack. The X register is not lost, it moves into the
Y register, and so on down the stack.
- h>hms --'Hours to hours/minutes/seconds conversion
LSTX
- This operator takes no arguments. It reads the X register
as a number of hours, and converts it to hh.mm.ssss form. See
the 'hms+' and 'hms>h' operators description for more
information.
- hms>h --'Convert hours/minutes/seconds to hour
LSTX
- This operator takes no arguments. It reads the X register
as a number in hh.mm.ssss form and converts the result to a
fraction of an hour. So, 1.30 would become 1.5, since one
hour and thirty minutes is equal to an hour and a half.
- hms+ --'Add in hours/min/sec fmt. X <- X + Y hms
LSTX
-
This operator takes no arguments. It adds X and Y as if
they were in the form: hh.mmssss. That is, the integer part
of the number is taken as hours, the first two digits after
the decimal point are taken as minutes, and all digits
after that are interpreted as seconds. For instance,
3.182014 would become 3 hours, 18 minutes, 20.14 seconds.
After the addition, the result is adjusted so that the
seconds and minutes fields do not equal or exceed sixty.
For example:
-
1.4020 <ENTER>
1.3052
hms+
- yields: 3.1112
- int --'Integer roundoff X <- (int)X LSTX
- This operator takes no arguments. It rounds the number in
the X register to the next integer closer to zero.
- frac --'Fractional part X <- frac(X) LSTX
-
This operator takes no arguments. It discards the integer
portion of X. If X is negative, it still discards the whole
part, so that
frac(-1.2) = -0.2
- round --'Round off to displayed value
- This operator takes no arguments. It rounds off the value
in the X register to the actual value displayed on the
screen. If the X register holds 1.2284, and the display mode
is 'fixed' and 'dsp 2', then the screen will display the
value '+1.23'. The 'rnd' function rounds off the internal
representation to match.
- rci --'Recall from I register
- This operator takes no arguments. It pushes the current I
value onto the stack, pushing the rest of the stack down to
accomodate it.
- sti --'Store in I register I <- X
- This operator takes no arguments. It stores the current X
value in I. The former value of I is lost, nothing else is
changed. Note that this function cannot be replaced by "sto
(i)" as that would invoke the indirection behaviour of the
"sto" function.
- dsz --'Decrement; skip if zero I <- I - 1
- This operator takes no arguments. It decrements the I
register. If a program is executing, and the I register is
zero after the decrement, then the next program step is
skipped.
- dsz(i) --'Decrement indirect; skip if zero
- This operator takes no arguments. It decrements the
memory register whose label matches I. If the register is
zero after the decrement and a program is executing, the next
program step is skipped.
- isz --'Increment; skip if zero I <- I + 1
- As 'dsz', but it increments the register.
- isz(i) --'Increment indirect, skip if zero
- As 'dsz(i)', but it decrements the register.
- x<>i --'Exchange X and I X <--> I
- This operator takes no arguments. It exchanges the
current X and I values.
- stat+ --'Add statistical data pair LSTX
- This operator takes no arguments. It takes the current X
and Y values and updates internal registers containing the
sum of: X, X^2, Y, Y^2, and X*Y. The X value is replaced by
the total number of data pairs collected. This function can
also be used if you are only processing X values, rather than
X,Y pairs. Just ignore the results from the 'Y' values. This
operator updates memory elements accessible to any running
program. These are, "_stats_sumx", "_stats_sumx2",
"_stats_sumy", "_stats_sumy2", "_stats_sumxy", "_stats_n",
and contain the sum of values of X, X squared, Y, Y squared,
X * Y, and the number of points, respectively.
- stat- --'Subtract statistical data pair LSTX
- As above, but it subtracts out the values from the
internal registers. This is usually used to remove erroneous
data pairs entered with 'sum+'.
- avg --'Obtain average X and Y values LSTX
- This operator takes no arguments. It replaces the current
X and Y values with the average values of X and of Y entered
with 'sum+'.
- sdev --'Obtain standard deviation of X and Y values
LSTX
- This operator takes no arguments. It replaces the current
X and Y values with the standard deviations of X and of Y
entered with 'sum+'.
- % --'Percentage operator X <- Y * X/100 LSTX
- This operator takes no arguments. It multiplies the top
two elements on the stack, and then divides by 100.
- %chg --'Percent change operator X <- (X-Y)*100/Y
LSTX
- This operator takes no arguments. It changes the value in
the X register to the percentage of Y by which X differs from
Y.
- clx --'Clear X value X <- Y
- This operator takes no arguments. It pops the stack,
discarding the X value and promoting the former Y value to
the new X value. Note that this is subtly different from the
clear operator on the HP-67, repeated invocations of which do
not clear the entire stack.
- rdown --'Roll stack down
- This operator takes no arguments. It rolls the stack so
that the X value goes to the bottom of the stack, and all
other registers move up one position, making the former Y
value into the new X value. This differs from the HP-67 roll
down operator in that it rolls only active stack elements.
The HP-67 has a stack size of four, and the X register is
always moved into the fourth position, even if fewer than
four stack elements were in use.
- rup --'Roll stack up
- This operator takes no arguments. It rolls the stack so
that the bottom stack element moves into the X position, and
all other stack elements move one level deeper. This differs
from the HP-67 operator in the same way as 'rdown'
above.
- lastx --'Retrieve LastX register
- This operator takes no arguments. It pushes the current
contents of LSTX onto the stack.
- clstk --'Clear stack space
- This operator takes no arguments. It deletes all stack
elements.
- clreg --'Clear memory registers
- This operator takes no arguments. It deletes all memory
registers, freeing the memory and returning it to the
machine.
- goto --'Move the program counter to a position
- This operator takes one argument. It moves the program
counter to the label or line number represented by the
argument. Line numbers are in the form of a decimal point
followed immediately by a numeric string. Valid labels cannot
begin with a decimal point, so there is no ambiguity. It can
be invoked with indirection, in which case it searches for
the label which matches the integer value of the I register,
for positive I, or steps back exactly N steps for negative I,
where N is the value of int(I).
- R/S --'Run/stop
- This operator takes no arguments. It halts program
execution immediately and returns to user mode. The current
return stack is not lost, so the program can be stepped
through from this point without losing subroutine
information. The program will continue after this instruction
if 'run' is entered without arguments. Note that a running
program hitting a R/S statement is, technically, an error, so
the calculator will sound or flash an alert if the terminal
supports that.
- sf --'Set flag
- This operator takes one or two arguments, the first one a
label or the indirection operator, and sets a binary flag
with that label identifier. If the argument list ends in the
string " clr", then this is stripped from the label and the
resulting flag is a clear-on-test flag. The clear-on-test
status is updated every time that the 'sf' operator is
called, so a given flag can be clear-on-test in one part of
the program, and explicit-clear-only in another. The program
keeps a list of all set flags. This is used to pass
information (usually on flow) between different parts of a
program. If the flag is already set it has no effect.
- cf --'Clear flag
- Unsets the flag named by the argument. If the flag was
not already set it is not an error.
The following commands are available only in immediate
mode:
- run --'Run a program
- This operator can take one argument, or no arguments. If
invoked with no arguments it runs from the current program
counter location. If invoked with an argument it runs from
that label. If the target label is a single character it can
be invoked with the M-<key> hot key.
- While a program is running it can be stopped by pressing
any key.
- prog --'Enter programming mode
- This operator takes no arguments. It allows the user to
key in programs. hp67 re-enters user mode when 'immed' is
entered.
- step --'Step through a program
- Executes the command under the current insertion pointer,
and advances the pointer to the next element.
- r/prog --'Load a program from a disk file
- This operator takes one argument, the pathname of the
text file which contains the program to load. The program
loaded is inserted after the current program counter
location. Care should be taken that this doesn't insert it
into the middle of another program segment, or that one will
be trashed efficiently. This function cannot be used inside a
program, and one loaded file cannot call another file to
load.
Variables and memories can be loaded this way also. When
loading the program starts out in programming mode, but if the
token 'immed' appears in the file then subsequent lines are
interpreted as if they had been issued in immediate mode. They
can put numbers on the stack, act on them with operators, store
them to memory labels, exactly as if the commands had been
typed at the keyboard. A later 'prog' token can switch back to
programming mode. The file is parsed until an error or the end
of file is encountered. Be careful not to leave a blank line at
the end of the file, since a blank line is interpreted as the
<<~ENTER~>> command.
- w/prog --'Save program elements
- This operator takes one argument, the pathname of the
text file which should be written with the program
instructions. The text is written out, including
comments.
- w/data --'Save memory elements
- This operator takes one argument, the pathname of the
text file which will be used to store non-zero memory
elements. The format is compatible with the input required
'r/prog' operator, so loading the file with that command
restores the memory as it appeared when the present when the
file is re-loaded, unless those elements have the same label
as the ones being loaded. Note that there is a possibility
for unexpected behaviour here, if a program element existed
and was exactly zero, then was saved, and re-loaded after the
element was assigned a non-zero value, then the new value is
not reset to zero. To ensure that the program memory is
exactly the same as that which was saved, it is recommended
that you invoke 'clreg' before loading the memory.
The following commands are available only in programming
mode:
- label --'Create a label
- This operator takes one argument, a printable ASCII
string which does not begin with a period. It is used as the
target of branches and M-<key>.
- gosub --'Go to a subroutine
- This operator takes one argument, a valid label or the
indirection notation. It pushes the return address onto an
internal stack and continues execution from the label. The
'rtn' statement returns from the subroutine. As with other
features of this program, subroutine nesting is limited only
by the total memory available.
- rtn --'Return from a subroutine
- This operator takes no arguments. It pops a return
address and continues execution from there. If there are no
more entries on the stack it returns to the user mode.
- f? --'Check flag
- This operator takes one argument. If the flag pointed to
by the label is not set then the next program step is
skipped. If the flag is a clear-on-test flag, then it is
cleared.
- x==0 --'Check X=0?
- This operator takes no arguments. If the value contained
in the X register is not zero then the next program step is
skipped.
- x==y --'Check X=Y?
- As above, but the condition for executing the next
program step is that X must equal Y.
- x!=0 --'Check X not equal to zero?
- See above, you figure it out.
- x!=y --'Check X not equal to Y?
- See above, you figure it out.
- x<0 --'Check X is negative?
- See above.
- x<=y --'Check X is not greater than Y?
- See above.
- x>0 --'Check X is positive and non-zero?
- See above.
- x>y --'Check X is greater than Y?
- See above.
- clprg --'Clear program space
- This operator takes no arguments. It can only be executed
from programming mode. It erases all program elements.
- immed --'Exit programming mode
- This operator takes no arguments. It exits programming
mode and enters user mode. <CTRL>-D is a shorthand hot
key for this.
MORE NOTES ON PROGRAMMING HP67 CALCULATOR
This program maintains the concept of a program counter. The
program counter marks the place where the next program step
will be inserted if you're writing a new program, and marks the
place where the next instruction will be executed in user or
stepping mode. It is incremented immediately before the current
command is executed. If the program hits an 'rtn' statement,
then, the program counter is pointing to the statement after
the calling 'gosub' when it returns. Typing 'run' without
arguments at this point will send the program on from
there.
When the user or program issues a 'goto label' command the
label is searched forward from the statement after the current
program counter, if necessary cycling round at the end and
coming back from the first program location, until it either
finds the label or returns to its starting point. The latter
results in an error. Notice that labels need not be
unique, and the 'goto', 'gosub', and 'run' statements will
all branch to the first label after the current program counter
which matches the search string. A 'goto .linenum' command has
no such ambiguity, as all line numbers are necessarily
unique.
The return address stack is flushed out when any one of the
following occurs:
- 1)
- the user enters 'prog' mode and deletes or adds a
step.
- 2)
- the user issues a 'load' command which changes program
memory.
- 3)
- the user isses a 'run' or 'step' command with a label. If
no label is given the stack is NOT cleared.
If the return stack is cleared a subroutine or two deep into
your program you will not be able to resume it and expect it to
run to completion. The next 'rtn' statement, instead of
returning to the calling gosub, will return to user mode
instead.
When writing functions which might be used as subroutines
later, take care to choose variable names which are unlikely to
collide with those of the caller, for instance by appending to
all names a string identifying the function of the module. If I
implement name scoping at some future time this won't be so
critical. If the function modifies the I register, that value
should be saved on entry and restored just prior to exit, so
that the calling function's behaviour is not affected.
The R/S command can be used as a breakpoint. Insert it in
the program, and execution will halt when it hits that line,
then you can step through with the "step" function, or press
"run" and the program will continue from the point following
the breakpoint. Also, by putting R/S immediately after a
decision command like "x>y", "f?", or "x==0" you can make
conditional breakpoints.
MAGIC TO KEEP IN MIND
The memory label "(i)" (without the quotation marks) is
special. Any attempt to assign to it or read from it results,
instead, in access to the memory element whose label is the
string representation of the integer value of the I register.
To change or retrieve the value of the I register, the sti or
rci functions must be used.
Similarly, the goto label "(i)" and flag "(i)" are special,
see above.
The statistical functions update special named memory
elements, see the description of "stat+".
Labels cannot begin with a '.'
The '#' character begins a comment.
Flags can be made to clear on test.
FILES
- $HOME/.hp67rc
- This file, if it exists, is read in as a preloaded
program file, unless overridden by command line arguments or
the HP67PROGRAM environment variable.
ENVIRONMENT
- HP67PROGRAM
- This variable, if set, contains the name of the program
file to read when the emulator starts up, unless overridden
by command line arguments. If this variable is set, and the
$HOME/.hp67rc file exists, then the latter will be
read only if the former does not resolve to a readable
file.
ABOUT THE PROGRAM
Version 1.0 completed Feb 11, 1997
Copyleft GPL 1997 by Christopher Neufeld
Distribute freely so long as this file is included.
This program is essentially a re-write of the RPN classic
desk accessory for the Apple ][GS which I released in 1993. If
anybody out there has actually used the CDA version, please let
me know.
AUTHOR
Christopher Neufeld
Index
- NAME
- SYNOPSIS
- DESCRIPTION
-
- OPTIONS
- SPECIFICS OF THE HP-67 EMULATOR
- Command entry format
- Display layout
- Curses magic behaviour
- LIST OF COMMANDS
- MORE NOTES ON PROGRAMMING HP67
CALCULATOR
- MAGIC TO KEEP IN MIND
- FILES
- ENVIRONMENT
- ABOUT THE PROGRAM
- AUTHOR