[comp.sources.misc] v14i039: pac - the ultimate UNIX calculator, part 1 of 5

istvan@hhb.UUCP (Istvan Mohos) (08/04/90)

Posting-number: Volume 14, Issue 39
Submitted-by: istvan@hhb.UUCP (Istvan Mohos)
Archive-name: pac/part01

The panel calculator "pac" (posted to comp.sources.misc in 5 parts)
has been dubbed "the ultimate on-screen calculator for UNIX" by the
network monitor of The C User's Journal (Volume 7, Number 8).  Major
features include:

o   16 cells nonvolatile memory (checkbook balance, phone numbers, etc.)
o   asynchronous real-time clock
o   separate checkbook balancer window (for summing lists of numbers)
o   ASCII to decimal to octal to hex translation (find out what ^M is)
o   22 predefined conversions (metric, temperature, etc.)
o   user-definable, non-volatile conversions (dollar to yen, etc.)
o   compound interest/mortgage payment solver (play the "what if?" game)
o   amortization schedule (monthly payment list) file writer
o   function help window (type "help" or just "?" or "help [subject]")
o   optional automatic calculator session recording to files
o   trigonometric functions
o   number base conversions (independent in/out bases, between 2 and 16)
o   programmable precision: btw 0 and 32 digits past the decimal point
o   bitwise AND, OR, NOT, XOR, TWOSCOMP
o   fully automatic and accessible push/pop stack memory
o   pi, planck, parallax, parsec... 30 math/physical constants in all
o   macro tokens from "atto" to "exa" (for ex: "356 micro + 125 milli")
o   predefined percent calculations (for ex: "65.7 p[ercent]of 290")

For its engine, "pac" uses interprocess pipes to the "bc" calculator.
The posted source has been successfully compiled and tested on:
Pyramid 90x, VAX 11-785, Apollo Domain-IX, Sun SPARCstation 1,
AT&T 6300+, Xenix286, DEC 8600.
"pac" will NOT work on SunOS 3.x systems due to bugs in SunOS "curses".

==============================CUT HERE==============================
#!/bin/sh
# This is a shell archive (shar 3.21)
# made 07/25/1990 19:26 UTC by istvan@istvan
# Source directory /rand/istvan/pac
#
# existing files WILL be overwritten
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#   1635 -rw-r--r-- Relnotes
#  27117 -rw-r--r-- pac.man
#    382 -rw-r--r-- README
#    881 -rw-r--r-- makefile
#  13508 -rw-r--r-- defs.h
#  14314 -rw-r--r-- maps.h
#   7256 -rw-r--r-- toktab.h
#   7762 -rw-r--r-- amort.c
#   6366 -rw-r--r-- atoi.c
#   5666 -rw-r--r-- bitwise.c
#  13160 -rw-r--r-- conv.c
#   7993 -rw-r--r-- convbase.c
#  11737 -rw-r--r-- display.c
#   3940 -rw-r--r-- error.c
#   7596 -rw-r--r-- file.c
#   7333 -rw-r--r-- help.c
#    871 -rw-r--r-- ierror.c
#  23768 -rw-r--r-- interpret.c
#   6967 -rw-r--r-- ledit.c
#   3586 -rw-r--r-- onlay.c
#   6229 -rw-r--r-- pac.c
#   5676 -rw-r--r-- pactok.c
#   1805 -rw-r--r-- pipes.c
#   3746 -rw-r--r-- stack.c
#   3735 -rw-r--r-- system.c
#   3249 -rw-r--r-- time.c
#   8736 -rw-r--r-- total.c
#     48 -rw-r--r-- version.c
#   4228 -rw-r--r-- work.c
#
if touch 2>&1 | fgrep '[-amc]' > /dev/null
 then TOUCH=touch
 else TOUCH=true
fi
# ============= Relnotes ==============
echo "x - extracting Relnotes (Text)"
sed 's/^X//' << 'SHAR_EOF' > Relnotes &&
XPac is a slightly overambitious visual calculator for Unix systems.
XIn spite of its minor structural problems, pac is the
X"everything you ever wanted in a calculator" calculator, providing:
X
Xo   16 cells nonvolatile memory (checkbook balance, phone numbers, etc.)
Xo   asynchronous real-time clock
Xo   separate checkbook balancer window (for summing lists of numbers)
Xo   ASCII to decimal to octal to hex translation (find out what ^M is)
Xo   22 predefined conversions (metric, temperature, etc.)
Xo   user-definable, non-volatile conversions (dollar to yen, etc.)
Xo   compound interest/mortgage payment solver (play the "what if?" game)
Xo   amortization schedule (monthly payment list) file writer
Xo   function help window (type "help" or just "?" or "help [subject]")
Xo   optional automatic calculator session recording to files
Xo   trigonometric functions
Xo   number base conversions (independent in/out bases, between 2 and 16)
Xo   programmable precision: btw 0 and 32 digits past the decimal point
Xo   bitwise AND, OR, NOT, XOR, TWOSCOMP
Xo   fully automatic and accessible push/pop stack memory
Xo   pi, planck, parallax, parsec... 30 math/physical constants in all
Xo   macro tokens from "atto" to "exa" (for ex: "356 micro + 125 milli")
Xo   predefined percent calculations (for ex: "65.7 p[ercent]of 290")
X
XThe pac process forks pipes to the 'bc' Unix calculator.
XThe posted source has been successfully compiled and tested on:
XPyramid 90x, VAX 11-785, Apollo Domain-IX, Sun SPARCstation 1,
XAT&T 6300+, Xenix286, DEC 8600.
X
XPac will NOT work on Sun2 or Sun3 computers due to insoluble problems
Xin their implementation of "curses".
X
SHAR_EOF
$TOUCH -am 0221175390 Relnotes &&
chmod 0644 Relnotes ||
echo "restore of Relnotes failed"
set `wc -c Relnotes`;Wc_c=$1
if test "$Wc_c" != "1635"; then
	echo original size 1635, current size $Wc_c
fi
# ============= pac.man ==============
echo "x - extracting pac.man (Text)"
sed 's/^X//' << 'SHAR_EOF' > pac.man &&
X.TH PAC 1 ""
X.UC 4
X.SH NAME
X.nh
X\fBpac\fR - panel calculator
X.SH SYNOPSIS
X.B pac
X.SH DESCRIPTION
X\fBpac\fR is an interactive calculator,
Xresembling a ``panel'' or ``page'' editor.
XThe interface is simple: the user enters
Xnumbers and arithmetic operators, \fBpac\fR displays the result.
XAlternate capabilities to the CALCULATOR include an
XASCII to decimal to octal to hexadecimal converter ATOI,
Xa checkbook balancer TOTAL,
Xa loan payment and amortization program LOAN, an
Xeditor for the expandable ``conversions data base'' NEWCONVERSION,
Xtime of day CLOCK; as well as session recording to files.
XOperating the alternate capabilities is intuitively obvious
Xand is helped along by the format of the display.
X.LP
XThe \fBpac\fR panel is a screen 23 lines by 78 characters,
Xpartitioned by inverse video borders into
Xsubwindows.  The CALCULATOR
Xis a rectangle 4 lines deep by 44 characters wide,
Xlocated in the upper left corner of the panel,
Xsimulating a hand-held calculator: echoing numbers and
Xoperators typed to the first three
Xlines, displaying the evaluated result
Xin the fourth line upon \fIRETURN\fR.  Control characters,
Xshown along the borders as first characters of mnemonics,
Xprovide immediate state switching to and from alternate tools.
X.SH LINE EDITING
XA selected function comes to life with the cursor
Xin the home position of a subwindow managed by the function.
XThe user directs input to this portion of the screen under the
Xcontrol of a primitive line editor.
X.LP
XNormally the typed characters are echoed and contribute to
Xthe input string.  Characters which the
Xtool is not equipped to deal with are not echoed, and are ignored
Xby the editor.  Control characters (also not echoed)
Xselect alternate tools, or
Xprovide exit from the program.  A number of keys are commands to
Xthe line editor only, allowing cursor positioning and input correction.
XThe editor keys and their effect may vary slightly,
Xdepending on the currently active \fBpac\fR tool.
X.LP
XThe first character echoed to a line,
Xnormally erases the previous input string.
XIn the CALCULATOR function, the line editing \fI=\fR key
Xrestores the old input string for editing.  A string beginning
Xwith the \fI#\fR character is considered a comment.
XComments are helpful if the user is recording the session, or
Xfor annotating scripts.
XAnother line editing character specific to the CALCULATOR
Xwindow is the pipe (|), which
Xbrings the cursor to the left edge of the following window line.
X.LP
XIf the input string reaches the
Xright line boundary, additional characters overwrite the rightmost
Xcharacter, except in the CALCULATOR function where the three lines of
Xthe input window conceptually form a single string.
XTyping \fIRETURN\fR triggers the interpretation of the input string.
XRegardless of the cursor position at the time of \fIRETURN\fR,
Xall data on the line is evaluated.  If the user did not type
Xcharacters prior to \fIRETURN\fR, a repeat of the previous string,
Xor a tool-specific default string is the assumed input.
X.LP
XA summary of the edit keys is always visible in an inverse video bar
Xrunning vertically in the center of the screen.
XEditing characters include \fIDELETE\fR and \fIBACKSPACE\fR,
Xboth of which delete characters
Xunder the cursor and move bytes at the right of the cursor
Xto the left.
X.LP
X\fIControl-C\fR in the CALCULATOR function, \fISPACE\fR in the
Xcheckbook balancer function, clear a line from the cursor to
Xits end; in the checkbook balancer function a \fIControl-C\fR
Xclears (zeroes) the entire window.
XStraight brackets \fI[  ]\fR move the
Xthe cursor non-destructively to the left or right.
XIn the CALCULATOR function, curly braces \fI{  }\fR move the cursor
Xto the line above or below, while
Xthe ``greater than''
Xsign \fI>\fR switches to \fIinsert mode\fR:
Xcharacters already to the right of the
Xcursor are pushed further to the right with each new character added.
XThe ``less than'' sign \fI<\fR, the \fIESCAPE\fR key or a
X\fIRETURN\fR end the \fIinsert mode\fR.
X.SH CALCULATOR OPERATION
XInput begins at the top left byte of the CALCULATOR window,
Xand may consist of multiple statements separated
Xby semicolons.  After \fIRETURN\fR, the input is broken down
Xto a list of tokens.
XCompound tokens contain one or more alphanumeric characters,
Xunderscores and periods; simple tokens are single,
Xnon-alphanumeric characters from the set:
X.LP
X.RS
X; % + - * / ^ ( ) \\ ' ? ! #
X.RE
X.LP
XA subset of simple tokens are the math operators
X\fI%\fR, \fI+\fR or \fI-\fR, \fI*\fR or \fI/\fR, \fI^\fR
X(in increasing order of operator precedence).
XThe percent sign stands for the ``modulo'' operation, the asterisk
Xstands for multiplication, the circumflex for exponentiation.
XOnly integer exponents are allowed.
X.LP
XTokens are delimited by commas or spaces, by the appearance of the
Xnext simple token, or by the end of the input line.
X.LP
XNumbers are a subset of compound tokens, formed entirely from
Xthe digits 0-9, the hexadecimal digits a-f or A-F, and the
Xperiod character.
X.LP
XDuring parsing, commas and spaces are removed, and successive
Xnumbers are concatenated to form a single number.
X.LP
XThe resulting token list is passed to the interpreter, which
Xevaluates each token in a normal, left-to-right sequence.
XA \fBpac\fR lookup table is searched for a match to the token.
XA match proves the token to be a \fBpac\fR control word, processed
Ximmediately.  This preprocessing may affect other tokens to
Xthe left or right of the control word; and in most cases the
Xaffected tokens (including the control word) are replaced
Xby a single number.
X.LP
XIf the token does not match a control word, any lower case a-f
Xcharacters of the token are upcased.
X.LP
XFrom the interpreter, the string
Xis passed to the \fBbc\fR calculator
Xthrough an inter-process pipe.
XBc evaluates the math expression,
Xand returns the result to \fBpac\fR for
Xformatting and display.  \fBpac\fR
Xprints the result in the fourth (bottom)
Xline of the CALCULATOR window.
X.LP
XThe \fIprecision\fR variable controls
Xthe number of digits printed to the right of a decimal point.  This
Xvariable can be set with the \fIprecision n\fR  or 
X\fIpr n\fR command; n values may range from 0 to 32.
XResults with greater than \fIprecision\fR fractional digits
Xare rounded.  Fractions too small to show up within the
Xprecision range cause an underflow error.  User selectable number
Xformatting and justification controls the final
Xappearance of the result.
X.LP
XExamples of CALCULATOR input:
X.LP
X.nf
X.RS
X.ta \w'(998 \fImicro\fR + .000002)\fImega\fR'u+2n
X77+88+99 - 66/(3 * 2)
X4.5  *  \fIpi\fR	---  using the constant \fIpi\fR
X12.785 + \fIs\fR	---  add 12.785 and stack variable \fIs\fR
X12.785 + \fIs\fR; \fIsto j\fR	---  as above; copy result into \fIj\fR
Xf + a	---  add hex numbers (dec15 + dec10)
X\fIp\fR + \fIq\fR	---  add stack variables \fIp\fR and \fIq\fR
X3.3^4	---  the fourth power of 3.3
X27^ (-3)	---  1 / 19683
X7! - 99	---  factorial of 7, minus 99
X(-5) * 40	---  using the unary minus
X(998 \fImicro\fR + .000002)\fImega\fR	---  1000
X32/(16/(8/(4/(\fIm\fR * 2/\fIm\fR))))	---  8 (if stack variable \fIm\fR not equal 0)
X+10	---  add 10 to the previous result
X-10	---  subtract 10 from the previous result
X- 60 / 3	---  subtract 20 from the previous result
X* 5	---  multiply previous result by 5
X.RE
X.fi
X.LP
X\fBpac\fR stores results as digit strings, on 17 lines of screen
Xdisplay.  Each of the strings is a \fBpac\fR variable.
XThe first of these strings, CURRES,
Xis the result shown in the CALCULATOR window.
XCURRES is updated continuously and is
Xthe result of the most recently evaluated expression.  This value
Xcan be referenced by the \fI\\\fR (backslash) character:
X\fI9 + \\\fR adds CURRES and 9.  Any operator that unsuccessfully
Xlooks for an operand to its left, will automatically reference
XCURRES
X(as in the last four ``Examples of CALCULATOR input'' above).
XSyntax errors clear CURRES to zero.
X.LP
XThe other 16 strings constitute the \fIuser stack\fR,
Xa rectangular area directly below the CALCULATOR window.
XThe 16 lines of the stack are
Xlabeled by the letters \fIh\fR to \fIw\fR
Xin the left inverse video border.
XThese labels are also \fBpac\fR tokens, and can be input to
Xthe CALCULATOR instead of typing the string contained in a stack cell.
XNew results are automatically ``pushed'' on the stack, unless the
X\fBpac\fR command \fIstack off\fR prohibits this.
X.LP
X\fBpac\fR key words for explicitly
Xmanipulating stack contents are
X\fIclr\fR, \fIdup\fR, \fIpop\fR, \fIpll\fR, \fIpsh\fR,
X\fIsto\fR, \fIswp\fR.
XThese operators can be input to the CALCULATOR regardless
Xof whether the stack is \fIon\fR or \fIoff\fR.
XA stack operator normally references the single-character
Xstack label immediately following the operator.
XFor example, \fIpop m\fR removes the number contained in \fIm\fR,
Xand moves all stack strings located below \fIm\fR up one position;
X\fIclr p\fR substitutes the number in stack cell \fIp\fR with zero.
XIf a stack label is not given,
XCURRES is the subject of the stack operation, except that \fIclr\fR,
Xreplaces the value of each stack variable with 0.
X.LP
XThe \fBpac\fR keyword \fIibase\fR (abbreviated version: \fIib\fR)
Xfollowed by an integer or a variable in the range of 2 through 16,
Xcan select an input base other than decimal.
XThe command
X.LP
X.RS
X\fIib\fR 2; 1011 0100 0010
X.RE
X.LP
Xas an example, results in
Xthe decimal display of ``2882''.
X.LP
XThe effect of the \fIib\fR command lasts from the time it was
Xfirst encountered in the input, to the end of the
Xinput string; then \fBpac\fR automatically
Xreverts to the original input base.
XTo permanently change the input base,
Xthe command \fIstaybase on\fR
X(abbreviated version: \fIsb\fR) should be issued.
XThe effect of \fIstaybase on\fR lasts until
Xa \fIstaybase off\fR commands cancels it.
XOutput radix is similarly controlled by the \fIobase n\fR
X(or \fIob n\fR) command for n values 2-16; and
X\fIstaybase\fR effects the permanence of input
Xand output radices in tandem.
X.LP
XSome useful CALCULATOR operators are:
X.RS
X.TP "\\w'the conversion operator\ \ 'u
Xthe bitwise operations
X\fIand or xor not twoscomp\fR (abbr.:\fItc\fR)
X.TP
Xthe percent operations
X\fIpplus pminus pdiff pversus pequal pof\fR (abbr.: \fIpp pm pd pv pe po\fR)
X.TP
Xthe conversion operator
X\fIto\fR
X.RE
X.LP
XExamples:
X.LP
X.nf
X.ta 3i +1.5i
XBinary AND of 9999 and 122:	9999 \fIand\fR 122	---  10
XBinary NOT of 9999 in 16 bit wide field:	9999 \fInot\fR 16	---  55536
XAdd 6.5 percent to 3500:	3500 \fIpplus\fR 6.5	---  3727.5
XPercentage increase from 3300 to 3500:	3300 \fIpdiff\fR 3500	---  6.06
XIf 4778 is 100%, what % is 2389:	4778 \fIpversus\fR 2389	---  50
XWhat is 75% of 4000:	75 \fIpof\fR 4000	---  3000
XIf 40% of a sum is 50, what is the sum:	40 \fIpequal\fR 50	---  125
XConvert 1225 inches to centimeters:	1225 \fIto cm\fR	---  3111.5
X.fi
X.LP
XThe \fBpac\fR tokens
X\fIsin\fR(x), \fIcos\fR(x), \fIexp\fR(x), \fIlog\fR(x), \fIarct\fR(x)
Xare used as substitutes for the \fBbc\fR
X``s(x), c(x), e(x), l(x), a(x)'' functions, respectively.
XInput values and results are radians.
X.SH CALCULATOR ENVIRONMENT
XEnvironment control operators are used to customize
Xthe CALCULATOR to the user's liking.
XAs with the other \fBpac\fR tokens, a certain redundancy is apparent
Xin naming the variables: two-character abbreviations are
Xgenerally accepted as input tokens.
X.LP
XWhen exiting \fBpac\fR, an attempt is made to
Xwrite a
X``.pacrc'' file in the user's home\fR directory, unless the
X\fIdontsave\fR command expressly forbids this.  In the .pacrc
Xfile, \fBpac\fR keeps a record of the current panel environment.  The
Xfile also contains the sixteen stack strings, and the
Xup-to-date ``units conversions list'' described under
XEDITING THE CONVERSIONS LIST, with any modifications
Xeffected by the user. Subsequent calls to
X\fBpac\fR begin by reading and resetting internal parameters
Xfrom the file data.
X.LP
XTo the right of the stack, the narrower GLOBALS window lists the
Xenvironment control operators and their current values.
XThe state-switching \fIControl-G\fR character
Xoverlays the GLOBALS window with a STATUS OPTIONS window, which
Xshows the abbreviated name of each control operator token, followed
Xby the values that this operator may assume.
XA second \fIControl-G\fR toggles the STATUS OPTIONS
Xwindow display back to GLOBALS,
Xunless the execution of a CALCULATOR string has already caused
Xthe re-display of the GLOBALS window.
X.LP
XThe variables \fIjustify\fR, \fIformat\fR,
X\fIhardform\fR, and \fIautotime\fR
Xcontrol the format of the \fBpac\fR display screen, and control
Xthe format of the file records.
XThe command \fIjustify left\fR
X(abbreviated: \fIju le\fR) instructs \fBpac\fR
Xto position the leftmost digit of the
Xresult in the bottom leftmost position of the CALCULATOR window.
XConversely, \fIjustify right\fR
X(abbreviated: \fIju ri\fR) specifies that the rightmost digit of the
Xresult be placed in the bottom rightmost
XCALCULATOR window position.
XAs a special case of \fIjustify right\fR,
X\fIjustify fix\fR outputs the result
Xin a fixed decimal point format.  In fixed
Xjustification, the number of digits displayed to
Xthe right of the decimal point is constant: the value of the
X\fIprecision\fR variable (0 through 32).
XThe \fIformat space\fR or \fIformat comma\fR
X(abbreviated: \fIsp\fR and \fIcm\fR)
Xcommand specifies that CURRES values are
Xto be displayed with spaces or commas respectively,
Xbetween groups of digits;
Xthis makes it easier to read long strings.
X.LP
XThe \fIhardform\fR command controls the format of a
Xrecording file which can be opened for writing with the \fIControl-F\fR
X(File)
Xcharacter, or for appending with the \fIControl-P\fR
X(Postpend)
Xcharacter.  The user is prompted for a file name; ``hardcopy'' is the
Xdefault.  Having opened the file, a new
X\fIControl-F\fR or \fIControl-P\fR will close it, otherwise the file
Xwill record calculator transactions until the exit from \fBpac\fR.
XThe command \fIhardform verbose\fR (abbreviated: \fIver\fR) resets
Xto the default file output format, saving
Xboth input and results, with
Xrecords separated by horizontal lines of dashes.
XThe commands \fIhardform terse\fR
X(\fIte\fR) and \fIhardform xterse\fR (\fIxt\fR) specify
Xsuccessively denser session recording.
X.LP
XThe command: \fIautoconv\fR automatically applies the selected
Xunit conversion formula to each new evaluation (CURRES)
Xprior to displaying the result.  For example, a list of dollar figures
Xmay be converted to pounds just by entering each dollar value.
X.LP
XThe macro command: \fIinit\fR resets the format, hardform,
Xibase, obase, justify, precision, stack, staybase, and
Xautoconv parameters to their default values.
X.LP
XThe special combination \fIhelp [token]\fR
X(or its abbreviated form \fI? [token]\fR)
Xoverlays the stack area with a portion of the token list,
Xhighlighting the selected token.  To the right of each
Xtoken  of the list, a very brief summary
Xof the token action is printed.  Stack display
Xresumes at the first subsequent stack activity.
X.SH ASCII CONVERSIONS
XDirectly to the right of the CALCULATOR window, a small rectangle
Xprovides immediate conversion between ASCII characters and their
Xdecimal, octal, or hexadecimal values, on a per-character basis.
XThe window is titled ATOI, and initially contains the following prompts:
X.LP
X.RS
X.nf
X^ A  asc
X^ D  dec
X^ O  oct
X^ X  hex
X.RE
X.fi
X.LP
XThe characters preceded by the caret \fI^\fR stand for the control
Xcharacters which cause temporary
Xtransition from the CALCULATOR state
Xto the ATOI window.  \fIControl-A\fR prompts the user to enter
Xany character on the top line of the ATOI window,
Xand immediately displays the decimal, octal,
Xand hex equivalents of this character beneath the input.
XContext then returns to the CALCULATOR.
X\fIControl-D\fR similarly, prompts for a decimal value
Xin the top line, in the 0-127 range.  Following a \fIRETURN\fR,
Xthe ASCII equivalent of the decimal
Xvalue, as well as the octal and hexadecimal versions are printed.
X\fIControl-O\fR prompts for an octal number
Xbetween \\000 and \\177; \fIControl-X\fR
Xprompts for a hexadecimal value between 0x0 and 0x7f.
XValues out of the
XASCII range are ignored, and the cursor stays on the first
Xline of the ATOI window until a legal value is selected.
X.SH AMORTIZATION
X\fIControl-L\fR (LOAN) changes context and moves the cursor
Xto the loan amortization window below ATOI.
XA second \fIControl-L\fR returns the user to the previous context.
XThe top three lines of the LOAN window are labeled
X``AMT'', ``%'', and ``YRS'' in the inverse video border to the
Xleft.  The user is expected to input a decimal string
Xas the ``loan amount'' (principal)
Xon the ``AMT'' line, an amortization (percent) rate in the second line,
Xand the life term of the loan (in years) on the third line.
XUp to two digits past the decimal point are significant
Xfor both the principal and the life term values,
Xthree digits past the decimal point are significant for
Xthe percent rate.
X.LP
XWhen all
Xthree lines contain non-zero values, the monthly payment on the proposed
Xloan is immediately displayed in the fourth line of the window, and the
Xcursor wraps back to the first line.  The user can now
Xrepeatedly adjust the amount, rate, or term values in an infinite loop,
Xby simply
Xtyping over the old values.  Each change causes an immediate update of
Xthe monthly payment figure.
X.LP
XTo dump the actual monthly amortization schedule to a file,
X\fIControl-B\fR
Xmoves the cursor to the last line of the LOAN window, where the
Xmonth/year date of the first payment is entered; then the user is
Xprompted for a file name on the bottom of the screen.  The amortization
Xfile creation involves substantial floating point math and string
Xformatting, and takes a few seconds to complete.
X.LP
XThe author has gleaned the amortization algorithm from
Xexamining actual bank loan printouts.
XWhile the \fBpac\fR method duplicates
Xthe bank samples exactly, different methods of rounding
Xmay possibly be employed by other lending institutions, resulting in
Xminor discrepancies between the two sets of figures.
X.SH CHECKBOOK BALANCER
XCashier's lists, checkbook tallies, score keeping, and
Xa number of book keeping activities involve entering and summing
Xvalues in columnar format.
X\fIControl-T\fR switches \fBpac\fR to the TOTAL window
Xdirectly overlaying the CONVERSIONS list.
XInitially, the TOTAL window consists of 19 lines
Xof zero values, and a bottom ``total'' line.
XThe lines are labeled in the
Xright inverse video border by the lower case letters \fIa\fR through
X\fIs\fR, and the ``total''
Xline is labeled by \fIt\fR.  As the
Xuser types in decimal values (followed by \fIRETURN\fR)
Xthe cursor advances to the next lower line, and the entered values are
Xautomatically summed to ``total''.
X.LP
XAt each \fIRETURN\fR, the most recently typed value is re-formatted
Xright justified, with the number of fractional digits
Xdictated by the user environment'
Xprecision value.  Negative values
Xare subtracted from the total.  The line may also
Xcontain a single \fI*\fR or \fI@\fR character, to effect
Xprice multiplication by item count.  As an example, ``64 @ 9.17''
Xis immediately converted to ``586.88''.
X.LP
XWhen nineteen items have already been entered and the cursor is
Xin line \fIs\fR, the input window wipes
Xitself clean and copies the current total
Xto the top line.  The cursor is then positioned at the beginning of the
Xsecond line, and the entry process can continue indefinitely.  It is
Xconvenient to refer to this paging
Xevent as a ``subtotal''.  At subtotal,
Xas well as at the exit from the TOTAL function,
Xthe current total is pushed into stack cell \fIh\fR (the top
Xvisible element of the user stack on the left side).  If the user stack
Xis \fIon\fR, its elements are shifted down one line, potentially
Xretaining a sequence of subtotal values.  The calculator
XCURRES value
Xis not affected by subtotals; the user must explicitly reference the
Xappropriate stack cells to transfer values to the
XCALCULATOR window for input.
X.LP
XSimilarly to the ``hardcopy''
Xfile used for keeping an automatic record of CALCULATOR
Xactivities, a separate ``hardtotal'' file may be opened
Xfor \fIwrite\fR or \fIappend\fR
Xwhile the checkbook balancer is active.
X``Hardtotal'' is supplied as the default file name, unless
Xthe user types in another name.
XThe file continues receiving snapshots of the entire TOTAL window at
Xevery subtotal (except receiving only the subtotal values
Xif the \fBpac\fR \fIhardform\fR variable is set to \fIxterse\fR),
Xand a final snapshot on exit from the TOTAL window.
X.LP
XTOTAL interprets decimal numbers only. In
Xaddition to digits, \fI+ - * @\fR and the normal line editing
Xcharacters, the TOTAL line editor also accepts
Xthe letters \fIa\fR through \fIt\fR and \fIA\fR through \fIT\fR.
XThe lower case letters cause the value in the corresponding line to
Xbe replicated in the line of the cursor
X(\fIt\fR replicates the current total).  Upper case 
Xalphabetics \fIA\fR through \fIS\fR relocate the cursor
Xto the line labeled by the corresponding
Xlower case letter; input then continues from this line.
XWhen the cursor is relocated this way, the digit string
Xalready in the line is not cleared; the new input will be
Xprepended to it.  A space typed clears the line from the cursor
Xto its end.
XUpper case \fIT\fR forces a stack push of the current total,
Xand the snapshot of the window written to an open ``hardtotal'' file.
XThe \fI#\fR character
Xis again a comment delimiter,
Xsignaling the editor to ignore it and any further input
Xuntil the \fIRETURN\fR.
XA second \fIControl-T\fR provides return to the previous context.  A
X``hardtotal''
Xfile may be explicitly closed prior to exiting TOTAL, or
Xit may be left open, awaiting recording of further TOTAL activities.
XEven after exiting TOTAL, the window remains visible over the
XCONVERSIONS list until a CALCULATOR conversion takes place.
X.SH EDITING THE CONVERSIONS LIST
XUnit conversion operations of the CALCULATOR
Xare based on a conversions data base, shadowed from a static list
Xinto dynamically allocated memory at initialization, and
Xmodifiable by the user.
XThe NEWCONVERSION editor for the conversions database
Xis entered with a \fIControl-N\fR,
Xtypically to add new conversions defined by the user,
Xbut occasionally to remove existing conversions, or to alter current
Xconversion factors.
X\fBpac\fR conversions are unidirectional,
Xconverting from units \fIA\fR to units \fIB\fR.
XSeparate conversions must be defined to convert from dollars to
Xpounds, and from pounds to dollars, for example.
XAn altered exchange rate between the dollar and the
Xpound may prompt the user to update the dollar-to-pound
Xand pound-to-dollar formulae.
X.LP
XEditing the conversions data base begins in a temporary window
Xoverlaying the CALCULATOR window.
XThe user is prompted to select between adding, removing
Xor altering a conversion.  Next the user enters a key
Xup to three characters long.
X.LP
XIf the removal or the alteration
Xof an existing conversion is selected,
Xthe ``conversion keys list'' is searched for a matching key;
Xthe key may be re-entered on error until a match is found.  When
Xchanging an already existing conversion, the user enters a new key
X(up to three bytes long) as the altered key value.
XFor the pound-to-dollar conversion, let's assume the key \fIus\fR.
XA new conversion key is inserted in
Xthe key list in alphabetical order.
XA thirteen characters long reference label is typed in next (typically
Xa ``from-units to-units'' pair), as a visual
Xreminder of the meaning of the key.  In our example, this may simply be
X\fIpound  dollar\fR.
X.LP
XThe new formula is entered at the bottom inverse video
Xbar.  The character set of the formula is limited to
Xdigits, math operators \fI+ - * / ^ %\fR,
Xdecimal point, left and right parentheses,
Xand the backslash character \fI\\\fR.
XNormal line editing characters may be
Xused to correct errors.  All numbers are assumed to be decimal.
XGiven the exchange rate of 1.75 dollars to the pound,
Xthe ``X pounds = Y dollars'' equation could be stated as
X``Y = X * 1.75'' and entered as
X.LP
X.RS
X\\ * 1.75
X.RE
X.LP
Xinto the data base.  When the formula is invoked in a later
XCALCULATOR conversion such as ``900 \fIto us\fR'',
Xthe backslash standing for X in the solution, will be substituted by
X``900'', followed by the multiplication by the constant to get
Xthe new (converted) value.  Though the conversion list
Xis stored in decimal format,
Xduring calculations the constant strings are
Xautomatically re-cast into the input radix in effect.
XThe converse operation: dollars to pounds, would have a different key,
Xa different label, and the following conversion formula:
X.LP
X.RS
X\\ / 1.75
X.RE
X.LP
XMore complex formulae are feasible; the formula need not start with a
Xbackslash; multiple backslashes may occur.
XHaving finished with the editing of the conversion, the most recently
Xadded conversion is shown selected in the center
Xof the CONVERSIONS window.  Context reverts to the calling tool.
X.SH CLOCK
X\fIControl-K\fR installs a date/hour/minute clock in the
Xright corner of the top inverse video border.
XTime is kept in a twelve-hour format; a period
Xfollowing the minutes denotes PM.  The clock operates asynchronously
Xand without affecting the rest of the program.  A second \fIControl-K\fR
Xturns off the clock.
XThe \fBpac\fR environment variable \fIautotime\fR may be enabled,
Xwith the effect that the clock appears automatically on entry to
Xthe program.
X.SH EXIT
X\fIControl-E\fR resets
Xthe terminal to cooked mode, writes the .pacrc file
X(containing the \fBpac\fR environment variables, stack, and the
Xconversion list) in the user's HOME directory;
Xand returns the user to the shell.
XThe cursor is moved to the line below the \fBpac\fR screen.
XFrom the CALCULATOR function, either \fIquit\fR or \fIexit\fR
Xhas the same effect.  The action of the
X\fITAB\fR character (\fIControl-I\fR)
Xor the equivalent token \fIbye\fR
Xis different in that the CALCULATOR stack is
Xcleared (all 0 values are saved in the .pacrc file), and
Xthe screen is cleared as well.
X.SH BUGS
XPhysical constants are defined to a few digits of precision only,
Xnot to the 32 digits maximum capability of the calculator.
XThere is
Xno guarantee as to the accuracy of the constant definitions;
Xthe program must be re-compiled to make improvements or changes.
X.LP
XParentheses are passed through the preprocessor to \fBbc\fR
Xinstead of being handled immediately.  For this reason,
Xone should avoid using \fBpac\fR operators (multi-byte non-numeric
Xwords, and the factorial operator \fI!\fR) inside open
Xparentheses.  Also, logical (bit) and percent operators should not
Xdirectly precede a left parenthesis.
X.LP
XThese same \fBpac\fR operators may force partial evaluations of the
Xinput string, often changing CURRES faster than it is possible
Xto visually update the result.  Explicit use of the CURRES token
X\fIBACKSLASH\fR is therefore discouraged, except during the
Xediting of conversion formulae.
X.LP
XThough \fBpac\fR traps error messages from \fBbc\fR, if the operating
Xsystem is running with a broken or incorrectly compiled/linked
X\fBbc\fR, the buggy executable may ``surprize'' the \fBpac\fR
Xprocess by deadlocking the pipes.
X.LP
XDue to its interactive nature, \fBpac\fR is not optimized for speed;
Xshell scripts are slow.
SHAR_EOF
$TOUCH -am 0725152590 pac.man &&
chmod 0644 pac.man ||
echo "restore of pac.man failed"
set `wc -c pac.man`;Wc_c=$1
if test "$Wc_c" != "27117"; then
	echo original size 27117, current size $Wc_c
fi
# ============= README ==============
echo "x - extracting README (Text)"
sed 's/^X//' << 'SHAR_EOF' > README &&
X
XIf you are running under sysV, make with the -DREALUNIX flag.
XVersion.c is created by the makefile, it is ok to loose it.
XThe target terminal must have at least 80 columns and 24 lines.
X
XIf the shell complains about printer problems in response to the
X'pac' command, it has found the printer accounting /etc/pac instead.
X
XThe man pages are in "pac.man", use "troff -man" to print.
SHAR_EOF
$TOUCH -am 0221163890 README &&
chmod 0644 README ||
echo "restore of README failed"
set `wc -c README`;Wc_c=$1
if test "$Wc_c" != "382"; then
	echo original size 382, current size $Wc_c
fi
# ============= makefile ==============
echo "x - extracting makefile (Text)"
sed 's/^X//' << 'SHAR_EOF' > makefile &&
X#
XCC=/bin/cc
X
X# for bsd:
XCFLAGS=-O
XLFLAGS=-ltermlib
XMFLAGS=
X
X# for sysV:
X# CFLAGS=-O -DREALUNIX
X# LFLAGS=
X# MFLAGS=
X
X# for AT&T 6300+:
X# CFLAGS=-Ml -s -DREALUNIX
X# LFLAGS=
X# MFLAGS=-Ml -s
X
X# for Xenix286 (contributed by Mark Seiffert --- rex!mgse!marks):
X# CFLAGS=-M2el -Ox -DREALUNIX -LARGE
X# LFLAGS=-F 5000 -s
X# MFLAGS=-M2el
X
X#.SILENT:
X
Xall: version pac
X
Xversion:
X	@/bin/rm -f version.c
X	@echo 'char *version = "'`date`'";' > version.c
X
XNONE=ierror.o version.o
XBOTH=convbase.o interpret.o
XTABS=pactok.o bitwise.o help.o
XMAPS=amort.o atoi.o conv.o file.o pac.o total.o
XDEFS=display.o error.o ledit.o onlay.o pipes.o stack.o system.o time.o work.o
X
Xpac: ${NONE} ${BOTH} ${DEFS} ${MAPS} ${TABS}
X	${CC} ${MFLAGS} ${NONE} ${BOTH} ${DEFS} ${MAPS} ${TABS} \
X	-lcurses ${LFLAGS} -lm -o pac
X
X${BOTH}: defs.h maps.h toktab.h
X${TABS}: defs.h toktab.h
X${MAPS}: defs.h maps.h
X${DEFS}: defs.h
SHAR_EOF
$TOUCH -am 0725152590 makefile &&
chmod 0644 makefile ||
echo "restore of makefile failed"
set `wc -c makefile`;Wc_c=$1
if test "$Wc_c" != "881"; then
	echo original size 881, current size $Wc_c
fi
# ============= defs.h ==============
echo "x - extracting defs.h (Text)"
sed 's/^X//' << 'SHAR_EOF' > defs.h &&
X/* defs.h */
X/**********************************************************************
X*    File Name     : defs.h
X*    Function      : definitions, declarations
X*                  :    this header is included in all .c files of pac
X*    Author        : Istvan Mohos, 1987
X***********************************************************************/
X
X#include <curses.h>
X#ifdef REALUNIX
X#include <fcntl.h>
X#else
X#include <sys/file.h>
X#endif
X#include <ctype.h>
X#include <signal.h>
X#include <math.h>
X
X#ifdef TRACE
X#define _TR   if (Trace) fprintf(Tf,">%s%s\n",&Ttabs[Tlev--],fid);
X#define TR_   if (Trace) fprintf(Tf,"<%s%s\n",&Ttabs[++Tlev],fid);
X#else
X#define _TR
X#define TR_
X#endif
X
X#define ZERO  (char *)0
X
X#define LBOUND    1            /* left (inverse) edge of screen */
X#define RBOUND    78           /* right (inverse) edge of screen */
X#define TOP       1            /* top (inverse) edge of screen */
X#define BOT       23           /* bottom (inverse) edge of screen */
X#define UTOP      (TOP + 1)    /* user top of calculator window */
X#define UBOT      (TOP + 3)    /* user bottom of calculator window */
X#define ACCUM     (TOP + 4)    /* result line under calculator window */
X#define ACCUMAX   44           /* max calculator,result width */
X#define URIGHT    46           /* right user boundary of calculator */
X#define DIGMAX    32           /* max calculator (numeric) digits */
X#define ULEFT     3            /* left user calculator boundary */
X#define MSG       (TOP + 5)    /* vertical location of error message */
X#define MSGLEFT   4            /* left boundary of error message */
X#define STACKLEFT 3            /* left boundary of stack (base) */
X#define STACKTOP  (TOP + 6)    /* upper boundary of stack */
X#define STACKBOT  (TOP + 21)   /* lower boundary of stack */
X#define STACKMAX  36           /* max stack width (including base) */
X#define STACKDEEP 16           /* max number of stack cells */
X#define MYBUF    300           /* scratch display buffer */
X
X#define ATOIX      50          /* leftmost char printed into ATOI */
X#define AMTY       7           /* vert location of loan AMT */
X#define PRCY       8           /* percent */
X#define YRY        9           /* years */
X#define PAYY      10           /* payment */
X#define DATY      11           /* start date */
X#define LOANX      44          /* leftmost char printed into LOAN */
X#define LOANSIZ    13          /* max width of LOAN line */
X#define LOANR      (LOANX + LOANSIZ - 1)
X#define STATMSG    44          /* leftmost char printed into STATUS */
X#define STATX      54          /* left edge of 3 char status flag */
X#define STATY      (TOP + 12)  /* ver location of first status string */
X
X                               /* status defaults */
X#define PREC_DFLT  2           /* precision (# of digits past dp) */
X#define IB_DFLT    10          /* input base */
X#define OB_DFLT    10          /* output base */
X#define DISA       0
X#define ENA        1
X#define AP         2
X#define STACK_DFLT ENA         /* new result gets pushed on stack */
X#define COMMA_      1
X#define SPACE_      2
X#define FORM_DFLT  SPACE_       /* put commas or spaces in numbers */
X#define ED_DFLT    ENA         /* unimplemented */
X#define JL         0
X#define JF         1
X#define JR         2
X#define JUS_DFLT   JR          /* right, left, or fixed dp on right */
X#define SB_DFLT    DISA        /* radix change effects current string */
X#define SHOW_DFLT  DISA        /* don't pfresh until done */
X#define FVER       0
X#define FTER       1
X#define FXTER      2
X#define HF_DFLT    FVER        /* file dump verbose, terse or xterse */
X
X#define REGLEFT    3           /* leftmost char of stack cell (base) */
X#define CONVLEFT   60          /* leftmost char of CONV. labels */
X#define KEYLEFT    74          /* leftmost char of CONV. 3 char key */
X#define FITCONV    (BOT - TOP - 1) /* max conv strings visible */
X#define CONVCOUNT  24          /* number of predefined conversions */
X#define FROMTOSIZ  14          /* conv. label size + \0 */
X#define KEYSIZ     4           /* conv key size + \0 */
X#define CONVMAX    (FROMTOSIZ + KEYSIZ - 1) /* conv string window siz */
X#define CENTER     11          /* non_curses pos. in conv window */
X#define CONVSEL    (CENTER - 1)/* original (default) selection */
X
X#define TREQ       2           /* update requests to print top line */
X#define BREQ       9           /* update requests to print bottom line */
X#define MSGLEN    13
X#define FBOUND    (ULEFT + MSGLEN) /* where the screen fname starts */
X#define BUFSTOP   (FBOUND - ULEFT) /* where fname starts in buffer */
X#define TITSIZ    (RBOUND - ULEFT + 1)
X#define TALYREQ    1
X#define FILEREQ    2
X#define POSTREQ    3
X#define TOTLREQ    4
X#define TAPPREQ    5
X#define LOANREQ    6
X#define CONVREQ    7
X#define EDITREQ    8
X
X#define NOTINLIST -1           /* not recognized by pac tokenizer */
X#define PIPEMAX   4096         /* guaranteed min size by UNIX */
X#define WINLINE   81           /* max screen line + \0 */
X#define LINEMAX   256          /* rough line size */
X
X#define INIT        0          /* prior to curses, to die properly */
X
X#define CYX       pyp=CY, pxp=CX
X#define PYX       move(CY=pyp, CX=pxp)
X/* all functions must return cursor to starting CY, CX coordinates */
X
X#define E_SYNTAX    1          /* bc errors */
X#define E_DIVBY0    2
X#define E_EXPONENT  3
X#define E_OVERFLOW  4
X#define E_BCEXEC    5
X
Xstruct stk_cell {
X    char cell[STACKMAX + 1];
X    struct stk_cell *link;
X};
X
Xstruct stk_cell *find();
Xchar *pactok();                /* seems to be missing in 4.2BSD */
Xchar *bitwise();
Xchar *substivar();
Xchar *numform();
Xchar *getenv();
Xchar *calloc(), *malloc();
Xchar *ctime();
Xchar *strcat(), *strncat(), *strcpy(), *strncpy();
Xchar *gets();
XFILE *fopen();
Xdouble atof();                    /* amortization variables */
Xlong time(), lseek();
Xunsigned alarm();
Xint  go_away();
Xint  cdate();
X
X#ifdef MAIN                    /* globals are defined in pac.c,
X                                  declared as externs elsewhere */
X
XFILE *Tf = NULL;
XFILE *Dfp = NULL;
Xchar *Home, Rcfile[LINEMAX];      /* pac environment */
Xint  Rcfd, Rcerr;
X
Xchar *Cb[] = {
X"pac          PANEL CALCULATOR                    ATOI    ",
X"pac          PANEL CALCULATOR                    ATOI    "
X};
Xchar *Sb[] = {
X"pac          PANEL CALCULATOR                    ATOI     CONVERSIONS  TO   ",
X"pac          PANEL CALCULATOR                    ATOI          TOTAL        "
X};
Xchar *Titlq[TREQ];
Xchar *Basq[BREQ];
Xchar *Bb[] = {
X"TAB bye  <CTRL> Exit Redraw File Postpend Klock Globals Loan Newconv Total  ",
X"<CTRL> File Postpend Toggle_back  copy: a...t  up_down: A...S  transfer: T  ",
X"file  write: hardcopy                                                       ",
X"file  contd: hardcopy                                                       ",
X"total write: hardtotal                                                      ",
X"total contd: hardtotal                                                      ",
X"amort write: hardamort                                                      ",
X"new  value =                                                                ",
X"new formula:                                                                "
X};
Xchar *Hardname =
X"hardcopy                                                       ";
Xchar *Totname =
X"hardtotal                                                      ";
Xchar *Amortname =
X"hardamort                                                      ";
X
Xchar Spreadbuf[PIPEMAX * 2];      /* expand user input for tokenizing */
Xchar Tokbuf[PIPEMAX];             /* strcomp against key list */
Xchar Mainbuf[PIPEMAX];            /* Mainbuf (result) from bc */
Xchar Convbuf[PIPEMAX];            /* converter result from bc */
Xchar Ubuf[PIPEMAX];               /* unrecognized tokens, to bc */
Xchar Controlbuf[PIPEMAX];         /* recognized tokens effect control */
Xchar *Tokp[PIPEMAX], *Last;       /* Spreadbuf pointers */
Xchar Rebuf[PIPEMAX];              /* work buffers */
Xchar Tmpbuf[PIPEMAX];
Xchar Mop[PIPEMAX];
Xchar Uwin_copy[(UBOT - UTOP + 1) * (URIGHT - ULEFT + 1)];
X
Xint Context   = INIT;             /* initial status values */
Xint Justify   = JUS_DFLT;
Xint Format    = FORM_DFLT;
Xint Stack     = STACK_DFLT;
Xint Hide      = 0;
Xint Dontsave  = 0;
Xint Clockstat = DISA;
Xint Show      = SHOW_DFLT;
Xint Autotime  = DISA;             /* no clock until user asks */
Xint Hf        = HF_DFLT;
Xint Ibase     = IB_DFLT;
Xint Obase     = OB_DFLT;
Xint Oldib     = IB_DFLT;
Xint Oldob     = OB_DFLT;
Xint Lastob    = OB_DFLT;
Xint Staybase  = DISA;
Xint Precision = PREC_DFLT;
Xint Edhelp    = ED_DFLT;
Xint Autoconv  = DISA;              /* Autoconverter feature */
Xint Convcount = CONVCOUNT;
Xint Convsel   = CONVSEL;
Xint Hardcopy  = DISA;
Xint Totcopy   = DISA;
Xint Painted   = FALSE;            /* don't push init vals on Stack */
X
Xdouble Amt;
Xdouble Years;
Xdouble Rate;
Xdouble Pymt;
Xdouble Showpymt;
Xdouble Intrst;
Xdouble I_mo;
Xdouble Months;
X
Xint Negative;
Xint Too_big;
Xint Has_dp;
X
Xchar *Base_str = "$$23456789 bcdefx";  /* formatting aids */
Xchar *Sp44 = "                                            ";
Xchar *Sp34 = "                                  ";
Xchar *Sp13 = "             ";
Xchar *Fix32 = "00000000000000000000000000000000";
Xchar *Emptycell = "  0                                 ";
X
Xchar Separator = ' ';             /* must agree with FORM_DFLT */
X
Xint A_ret = 0;
Xint B_ret = 0;
Xint A_write[2], A_read[2];        /* main bc process pipes */
Xint Nread;                        /* main bc process globals */
Xint B_write[2], B_read[2];        /* bc converter process pipes */
Xint Hc = -1;                      /* Hardcopy file fd */
Xint Tc = -1;                      /* Total file fd */
Xint Tqlev = 0;
Xchar *Thisyear;
Xint Do_conv, O_conv;              /* activate selected conv function */
Xint Convread;                     /* bc converter process */
Xint Topconv;                      /* top conversion of conv vindow */
Xchar *Convhom;                    /* conv malloc pointer */
Xchar Eq_buf[WINLINE];             /* new conv string input by user */
Xchar K_buf[KEYSIZ];               /* 3 char new key input by user */
Xchar L_buf[FROMTOSIZ];            /* new conv label input by user */
Xunsigned int Convhsiz;
X
X                                  /* predefined user conversions */
Xchar *Convlist[256][3] = {
X{"km2      acre", "acr", "\\*247.1"},
X{"gram avoir_oz", "av ", "\\*.035274"},
X{"fahr. celsius", "c  ", "(\\-32)*.55555555555555555555555555555555"},
X{"fluid_oz   cc", "cc ", "\\*29.573"},
X{"inch       cm", "cm ", "\\*2.54"},
X{"radian degree", "deg", "\\*57.295779513082321"},
X{"celsius fahr.", "f  ", "\\*1.8+32"},
X{"meter    foot", "ft ", "\\*3.2808"},
X{"avoir_oz gram", "g  ", "\\*28.3495"},
X{"liter  gallon", "gal", "\\*.26418"},
X{"cm       inch", "in ", "\\*.3937"},
X{"inversion    ", "inv", "1/\\"},
X{"pound      kg", "kg ", "\\*.45359"},
X{"mile       km", "km ", "\\*1.6093"},
X{"acre      km2", "km2", "\\*.004046"},
X{"kg      pound", "lb ", "\\*2.2046"},
X{"gallon  liter", "lit", "\\*3.7854"},
X{"foot    meter", "m  ", "\\*.3048"},
X{"km       mile", "mi ", "\\*.6214"},
X{"mile nautical", "nau", "\\*.8689784566"},
X{"nautical mile", "nmi", "\\*1.150776515"},
X{"cc   fluid_oz", "oz ", "\\*.03381"},
X{"degree radian", "rad", "\\*.01745329251994329"},
X{"sentinel     ", "|||", "1"}};        /* sentinel; do not remove */
X
Xint Status;                            /* exit for fatal */
Xint CX, CY;                            /* global cursor control */
Xchar Onebuf[STACKMAX + 1];             /* temp store for 1 stack cell */
Xint Statopts;                          /* Status display window flag */
Xstruct stk_cell Stk[STACKDEEP + 1];
Xint Bc_error;
Xint Trace;
Xint Tlev;
Xchar Ttabs[] = {"\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"};
Xint (*Save_sig[8])();
Xchar ierbuf[256];
X
X#else
X
Xextern FILE *Tf;
Xextern FILE *Dfp;
Xextern char *Titlq[];
Xextern char *Basq[];
Xextern char *Cb[], *Sb[];
Xextern char *Bb[];
Xextern char Spreadbuf[];
Xextern char Tokbuf[];
Xextern char Controlbuf[];
Xextern char *Tokp[], *Last;
Xextern int Negative, Too_big, Has_dp;
Xextern char Rebuf[];
Xextern char Tmpbuf[];
Xextern char Mop[];
Xextern char Uwin_copy[];
X
Xextern int Context;
Xextern int Justify;
Xextern int Format, Stack, Hide, Dontsave;
X
Xextern int  Ibase, Obase, Oldib, Oldob, Lastob, Staybase, Precision;
Xextern int  Show, Clockstat, Autotime;
Xextern char *Base_str;
Xextern int  CX, CY;
Xextern char Ubuf[], Mainbuf[], Convbuf[];
Xextern char *Sp44, *Sp34, *Sp13, *Fix32, *Emptycell;
Xextern char Separator;
Xextern int  A_write[], A_read[], A_ret, Nread;
Xextern int  B_write[], B_read[], B_ret, Convread;
Xextern int  Status, Painted;
Xextern char *Home, Rcfile[];
Xextern int  Rcfd, Rcerr;
Xextern char Onebuf[STACKMAX + 1];
Xextern int  Hardcopy, Hc, Hf;
Xextern char *Hardname;
Xextern char *Amortname;
Xextern char *Totname;
Xextern int  Totcopy, Tc, Tqlev;
Xextern int  Autoconv;
Xextern int  Convcount;
Xextern int  Convsel;
Xextern int  Do_conv, O_conv;
Xextern int  Topconv;
Xextern char *Convlist[][3];
Xextern char *Convhom;
Xextern char *Thisyear;
Xextern char Eq_buf[];
Xextern char K_buf[], L_buf[];
Xextern unsigned int Convhsiz;
Xextern int  Statopts;
Xextern struct stk_cell Stk[];
Xextern int  Edhelp;
Xextern int  Bc_error;
Xextern int  Trace;
Xextern int  Tlev;
Xextern char Ttabs[];
X
Xextern double atof();
Xextern double Amt;
Xextern double Years;
Xextern double Rate;
Xextern double Pymt;
Xextern double Showpymt;
Xextern double Intrst;
Xextern double I_mo;
Xextern double Months;
X
Xextern int (*Save_sig[])();
Xextern char ierbuf[];
X
X#endif
SHAR_EOF
$TOUCH -am 0221163890 defs.h &&
chmod 0644 defs.h ||
echo "restore of defs.h failed"
set `wc -c defs.h`;Wc_c=$1
if test "$Wc_c" != "13508"; then
	echo original size 13508, current size $Wc_c
fi
echo "End of part 1, continue with part 2"
exit 0