pkg://hp67-1.4-1.i386.rpm:72442/
usr/
man/
man1/hp67.1
info downloads
.\" TAB-
.TH HP-67 1 "" "V1.0"
.SH NAME
.I hp67
\- a scientific calculator in Reverse Polish Notation
.SH SYNOPSIS
.B hp67
[\-n|\-\-noexit] [\-\-program=program|\-p program]
[\-\-ignorercfile|\-i] [\-\-help|\-h]
.SH DESCRIPTION
.PP
This program emulates an HP-67 calculator with a few minor variations.
This calculator uses the 'Reverse Polish Notation' favoured by
Hewlett-Packard.
.PP
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:
.PP
To evaluate: (3 + 4*7) / (2 + 8^3)
.PP
You hit the following sequence of keys:
.RS
.nf
3 <ENTER>
4 <ENTER>
7 *
+
2 <ENTER>
8 <ENTER>
3 y^x
+
/
.fi
.RE
.PP
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.
.SS OPTIONS
.TP
.I "\-n, \-\-noexit"
Disable the CTRL-D exit key.
This
behaviour is desirable if the program is run from within a
dedicated xterm,
such as
.I via
the following shell script:
.IP
#! /bin/sh
#
/usr/X11R6/bin/color_xterm $@ -ls -tn xterm-color \\
-e hp67 --noexit &
.IP
This script can then be invoked, for instance, as follows:
.IP
hp67.sh -iconic -geometry +700+400
.IP
to produce a dedicated xterm window which cannot be aborted, short of
sending the program a killing signal.
.TP
.I "\-p program, \-\-program=program"
Load the program space with the named program during. Equivalent to
issuing the command
.B r/prog program
from the keyboard immediately when the program begins.
.TP
.I "\-i, \-\-ignorercfile"
Don't preload any programs.
.TP
.I "\-h, \-\-help"
Issue a usage message and exit.
.SH "SPECIFICS OF THE HP-67 EMULATOR"
.PP
.SH "Command entry format"
.PP
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:
.RS
12.493 12.4e-5 .008E4 1.2E+4
.RE
.PP
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.)
.PP
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:
.RS
.nf
+
sto speedoflight
dsp 9
fix
.fi
.RE
.PP
See the list of operations for details of which commands require
operands.
.PP
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.
.SH "Display layout"
.PP
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).
.PP
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.
.PP
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.
.PP
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.
.SH "Curses magic behaviour"
.PP
When operating in curses mode, hp67 performs some extra actions for
certain input sequences.
.PP
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.
.PP
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.
.PP
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.
.PP
Now, the input line supports a few special command sequences.
.PP
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.
.PP
The following are 'hot keys'. If they are entered in the first position
on a blank input line their functions will be invoked:
.IP "<DELETE>"
In immediate mode, invokes the "clx" function to delete
the top element of the stack. In program mode, deletes the
current program line.
.IP "M-<SPACE>"
In immediate mode, invokes the "step" function.
.IP "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>.
.IP "<CTRL>-D"
In immediate mode, exits the calculator. In program mode,
returns to immediate mode.
.IP "UP-ARROW"
In program mode, moves the program insertion/execution
pointer back one space.
.IP "DOWN-ARROW"
In program mode, moves the program insertion/execution
pointer forward one space (without executing the step).
.IP "{"
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.
.IP "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.
.PP
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.
.PP
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.
.SH "LIST OF COMMANDS"
.PP
The following commands are available either in programming or in user
mode:
.de CC
.IP "\\\\fB\\$1\\\\fP \\\\h'|7'\\$2 \\\\h'|35'\\\\fI\\$3\\\\fP \\\\h'|54'\\$4"
..
.CC "+" "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.
.CC "-" "Subtraction operator" "X \(<- Y - X" "LSTX"
As above, but it subtracts.
.CC "*" "Multiplication operator" "X \(<- Y * X" "LSTX"
As above, but it multiplies.
.CC "/" "Division operator" "X \(<- Y / X" "LSTX"
.CC "!" "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.
.CC "recip" "Reciprocal operator" "X \(<- 1 / X" "LSTX"
This operator takes no arguments. It replaces the value in the X
register with its reciprocal.
.CC "chs" "Change sign operator" "X \(<- -X" "LSTX"
This operator takes no arguments. It replaces the value in the X
register with its negative value.
.CC "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.
.CC "cos" "Cosine operator" "X \(<- cos(X)" "LSTX"
As above, but for cosine.
.CC "tan" "Tangent operator" "X \(<- tan(X)" "LSTX"
As above, but for tangent.
.CC "asin" "Inverse sine operator" "X \(<- asin(X)" "LSTX"
As above, but for inverse sine.
.CC "acos" "Inverse cosine operator" "X \(<- acos(X)" "LSTX"
As above, but for inverse cosine.
.CC "atan" "Inverse tangent operator" "X \(<- atan(X)" "LSTX"
As above, but for inverse tangent.
.CC "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.
.CC "square" "Square operator" "X \(<- X ^ 2" "LSTX"
This operator takes no arguments. It replaces the value in the X
register with its square.
.CC "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.
.CC "exp" "Exponential operator" "X \(<- exp(X)" "LSTX"
This operator takes no arguments. It replaces the value in the X
register with e^X.
.CC "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.
.CC "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.
.CC "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.
.CC "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.
.CC "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.
.CC "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.
.CC "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.
.CC "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.
.CC "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.
.CC "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.
.CC "rad" "Set radians mode" "THETA = radians"
As above, but it sets angles to radians.
.CC "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.
.CC "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".
.CC "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.
.CC "sto+" "Add to memory register" "<label> \(<- <label>+X"
This operator takes one argument, the memory label. It acts like the
'sto' operator, but rather than replacing the value in that memory
register, it adds the current X value to it. This operation is
available with indirection.
.CC "sto-" "Subtract from memory reg." "<label> \(<- <label>-X"
As above, but it subtracts X from the memory register.
.CC "sto*" "Multiply into memory reg." "<label> \(<- <label>*X"
As above, but it multiplies X into the memory register.
.CC "sto/" "Divide into memory reg." "<label> \(<- <label>/X"
As above, but it divides X into the memory register.
.CC "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.
.CC "r>p" "Rectangular to polar conversion" "" "LSTX"
This operator takes no arguments. It converts the pair (X,Y) into
polar form.
.RS
.nf
X \(<- sqrt(X^2 + Y^2)
Y \(<- atan2(Y,X)
.fi
.RE
.CC "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:
.RS
.nf
X \(<- X * cos(Y)
Y \(<- X * sin(Y)
.fi
.RE
.IP
The former Y value is lost.
.CC "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.
.CC "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.
.CC "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.
.CC "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.
.CC "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.
.CC "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:
.RS
.nf
1.4020 <ENTER>
1.3052
hms+
.fi
.RE
.IP
yields: 3.1112
.CC "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.
.CC "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
.RS
frac(-1.2) = -0.2
.RE
.CC "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.
.CC "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.
.CC "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.
.CC "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.
.CC "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.
.CC "isz" "Increment; skip if zero" "I \(<- I + 1"
As 'dsz', but it increments the register.
.CC "isz(i)" "Increment indirect, skip if zero"
As 'dsz(i)', but it decrements the register.
.CC "x<>i" "Exchange X and I" "X \(<-\(-> I"
This operator takes no arguments. It exchanges the current X and I
values.
.CC "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.
.CC "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+'.
.CC "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+'.
.CC "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+'.
.CC "%" "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.
.CC "%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.
.CC "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.
.CC "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.
.CC "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.
.CC "lastx" "Retrieve LastX register"
This operator takes no arguments. It pushes the current contents of
LSTX onto the stack.
.CC "clstk" "Clear stack space"
This operator takes no arguments. It deletes all stack elements.
.CC "clreg" "Clear memory registers"
This operator takes no arguments. It deletes all memory registers,
freeing the memory and returning it to the machine.
.CC "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).
.CC "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.
.CC "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.
.CC "cf" "Clear flag"
Unsets the flag named by the argument. If the flag was not already
set it is not an error.
.PP
The following commands are available only in immediate mode:
.CC "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.
.IP
While a program is running it can be stopped by pressing any key.
.CC "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.
.CC "step" "Step through a program"
Executes the command under the current insertion pointer, and
advances the pointer to the next element.
.CC "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.
.PP
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.
.CC "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.
.CC "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
'w/data' command was run. It does not erase memory elements which are
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.
.PP
The following commands are available only in programming mode:
.CC "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
'run' commands. For single-character labels you can use the shorthand
M-<key>.
.CC "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.
.CC "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.
.CC "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.
.CC "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.
.CC "x==y" "Check X=Y?"
As above, but the condition for executing the next program step is
that X must equal Y.
.CC "x!=0" "Check X not equal to zero?"
See above, you figure it out.
.CC "x!=y" "Check X not equal to Y?"
See above, you figure it out.
.CC "x<0" "Check X is negative?"
See above.
.CC "x<=y" "Check X is not greater than Y?"
See above.
.CC "x>0" "Check X is positive and non-zero?"
See above.
.CC "x>y" "Check X is greater than Y?"
See above.
.CC "clprg" "Clear program space"
This operator takes no arguments. It can only be executed from
programming mode. It erases all program elements.
.CC "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.
.SH "MORE NOTES ON PROGRAMMING HP67 CALCULATOR"
.PP
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.
.PP
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
.B 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.
.PP
The return address stack is flushed out when any one of the following
occurs:
.IP "1)"
the user enters 'prog' mode and deletes or adds a step.
.IP "2)"
the user issues a 'load' command which changes program memory.
.IP "3)"
the user isses a 'run' or 'step' command with a label. If no label
is given the stack is NOT cleared.
.PP
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.
.PP
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.
.PP
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.
.SH "MAGIC TO KEEP IN MIND"
.PP
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.
.PP
Similarly, the goto label "(i)" and flag "(i)" are special, see above.
.PP
The statistical functions update special named memory elements, see
the description of "stat+".
.PP
Labels cannot begin with a '.'
.PP
The '#' character begins a comment.
.PP
Flags can be made to clear on test.
.SH FILES
.TP
$HOME/.hp67rc
This file,
if it exists, is read in as a preloaded program file, unless
overridden by command line arguments or the
.Ev HP67PROGRAM
environment variable.
.SH ENVIRONMENT
.TP
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
.B $HOME/.hp67rc
file exists, then the latter will be read only if the former does not
resolve to a readable file.
.SH "ABOUT THE PROGRAM"
Version 1.0 completed Feb 11, 1997
.PP
Copyleft GPL 1997 by Christopher Neufeld
.PP
Distribute freely so long as this file is included.
.PP
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.
.SH AUTHOR
Christopher Neufeld
.br
<neufeld@physics.utoronto.ca>