RPN DOCRPN PAS+RPN COMDW RPN Calculator by Jon Dart 1866 Diamond St., San Diego 92109 May 4, 1984 RPN is a simple calculator program using Reverse Polish Notation. The source code is compatible with the TURBO PASCAL compiler (Version 1, 2 or 3). It could also be adapted to run on other versions of Pascal, such as UCSD or MT+, but if you want to do this, you're on your own. If you have used a Hewlett Packard calculator before, you will understand how RPN works. If you have never used an RPN calculator before, here is a brief description of how to use it: The calculator maintains a set of four registers which are organized as a stack. When you type in a number, and hit RETURN, the program stores the number in the top two levels of the stack (anything that was on the top of the stack before gets "pushed down" to levels 3 and 4). To add something to the number on the stack, enter a second number, followed immediately by a "+" (the add command). When you hit "+", the second number will be pushed onto the stack, it will be added to the number at stack level 2, and then the stack will be "popped" so that the sum is at level 1. This sounds complicated, but once you get used to it, it is easy. The basic rule is that you always enter the two numbers you want to operate on first, and THEN enter the operation: e.g. to add 2 and 3, type 2 RETURN 3 +. To add more numbers, you only have to keep entering the numbers and a plus sign, since the sum is always saved on the top of the stack. E.g. to add 34 and 45 and 56, type: 34 RETURN 45 + 56 +. The use of the stack for temporary storage can be illustrated by the following example. Suppose you want to add a 5% shipping charge and a 6% sales tax for items priced at $114.95. Type: 114.95 RETURN pushes 114.95 onto the stack 114.95 RETURN pushes an extra copy of 114.95 114.95 5% calculates 5% 5.75 X exchanges the top two levels 114.95 6% calculates 6% 6.90 + adds the shipping and tax together 12.65 + adds the shipping and tax to the price 127.60 Try this example and use the D command to look at the stack at each step. This will give you a good idea of how the calculator works. program rpncalc; {$X-} (* RPN calculator program by: Jon Dart Department of Anthropology UCSD C-001 La Jolla, CA 92093 Version 1.3, 18-Nov-84 *) (* compile with Turbo Pascal *) const ctrl_d = #4; bel = #7; bks = #8; cr = #13; ctrl_x = #24; space = #32; del = #127; width = 16; (* field width for numeric output *) stack_depth = 4; type stacktype = array[0..stack_depth] of real; numstr = string[12]; var cmds,numbers :set of char; decimals :integer; (* # decimal places to display *) i,numlen :integer; ch :char; numbuf :numstr; endofline,exit :boolean; stack :stacktype; function keyin:char; (* returns next key pressed on keyboard *) (* the key is not echoed *) var key :integer; begin repeat key := bdos(6,255); until key<>0; keyin := chr(key); end; procedure echo(ch:char); (* echo chars, print control chars. as "^A", etc. *) begin if ord(ch)>=32 then write(ch) else write('^',chr(ord(ch)+ord('A')-1)); end; function uc(ch:char):char; (* makes character upper-case *) begin if ch in ['a'..'z'] then uc:=chr(ord(ch)-ord('a')+ord('A')) else uc := ch; end; procedure give_instructions; begin writeln('Commands:'); writeln; writeln('+ = Add'); writeln('- = Subtract'); writeln('* = Multiply'); writeln('/ = Divide'); writeln('^ = Exponent'); writeln('% = Percent'); writeln('D = Display Stack'); writeln('R = Square Root'); writeln('W = Set Number of Decimals'); writeln('X = Exchange Top Two Levels of Stack'); writeln('^D = Exit to CP/M'); writeln('^X = Clear Entry'); writeln; end; procedure docommand(ch:char;var numbuf:numstr;var exit:boolean); (* do the command corresponding to character ch *) var temp, t, value :real; i,code :integer; decstr :numstr; error :boolean; procedure pop; (* pop stack *) var i :integer; begin for i:=0 to stack_depth-1 do stack[i]:=stack[i+1]; end; procedure push(value:real); (* push value onto stack *) var i :integer; begin for i:=stack_depth downto 2 do stack[i] := stack[i-1]; stack[1] := value; end (*push*); procedure numout(num:real); (* output num according to current format *) begin writeln(num:width:decimals); end; begin (* docommand *) error := false; if (length(numbuf) > 0) then begin (* decode number in numbuf *) val(numbuf,t,code); if code <> 0 then begin error := true; writeln('Illegal number') end else push(t); end else if ch=cr then push(stack[1]); if not error then case ch of '?': give_instructions; '+': begin stack[2] := stack[2] + stack[1]; pop; numout(stack[1]); end; '-': begin stack[2] := stack[2] - stack[1]; pop; numout(stack[1]); end; '*': begin stack[2] := stack[2] * stack[1]; pop; numout(stack[1]); end; '/': begin stack[2] := stack[2] / stack[1]; pop; numout(stack[1]); end; '^': begin stack[2] := exp(stack[1]*ln(stack[2])); pop; numout(stack[1]); end; '%': begin stack[2] := (stack[1]/100)*stack[2]; pop; numout(stack[1]); end; 'X': begin temp:=stack[2]; stack[2]:=stack[1]; stack[1]:=temp; numout(stack[1]); end; 'D': begin for i:=1 to stack_depth do numout(stack[i]); end; 'R': begin stack[1]:=sqrt(stack[1]); numout(stack[1]); end; 'W': begin write('Number of Decimals? '); readln(decstr); if length(decstr)>0 then begin val(decstr,value,code); if code=0 then begin decimals := trunc(value); numout(stack[1]); end else Writeln('Illegal number.'); end; end; cr: begin numout(stack[1]); end; ctrl_d: exit:=true; ctrl_x: (* do nothing *); end (*case*) end (* docommand *); begin (* main program *) lowvideo; writeln; writeln('RPN Calculator'); writeln('by Jon Dart ... Version 1.3 (18-Nov-84)'); give_instructions; cmds := ['+','-','*','/','%','^','X','D','R','W','?',ctrl_d,ctrl_x, cr]; numbers := ['0'..'9','.']; exit := false; decimals := 2; for i:=1 to stack_depth do stack[i]:=0; repeat write('#'); numbuf := ''; numlen := 0; endofline := false; repeat ch := uc(keyin); if ch in cmds then (* have command *) begin if ch <> cr then echo(ch); writeln; docommand(ch,numbuf,exit); endofline := true; (* treat command as end of line *) end else if ch in numbers then begin write(ch); numbuf := numbuf + ch; numlen := numlen + 1; end else if ch in [bks,del] then begin if numlen > 0 then begin write(bks,space,bks); delete(numbuf,numlen,1); numlen := numlen - 1; end end else write(bel); (* error, ding bell *) until endofline; until exit; end.  ͫCopyright (C) 1985 BORLAND IncBHeath/Zenith H89ctedPqtqY ELE MKp1q1~7#~= oͦkԄ!!"~#(}:$= +*!5!*!!:(2!5:(>2!!!:O::O:!*! !45(! +/ 0y0( d!k5!{5__o&  :(͠|(  *"x2y( >28!"9!! og2"">~22 9/4*9 Co&ͦͣ} [ (!e{ͦA8Q0G: x@!\w# (͂ ?(*( .( w^. ^!h6# (?( *( ͂( w#>?> w#ͦ 8 !ɿ .,;:=?*[]<>{}a{ |ʹ}ͽƐ'@'7||}>2ͯ*Bڨ  "og"2>2! ""*B"[Ru*"^#V#^#V#N#FO/o&9O/o&9!9(> (G!9 w#Eͺw}8' RB0 >' RqRR!+ Ͱ R!+ Ͱ r!+ Ͱ r!+ Ͱ r!# Ͱ r!+ Ͱ T]KB!z> S>))0 = | |̀̀DMgo>jB0 7?= H͒<z5a)a<z {0Gɯgo||~}||/g}/o#}o&K[xAJSJDM!b"!6J"DM'd } ) W _}8(8J`9{T]=o`9y ) >' ́ ͬ͗ }>' xˆ }} ˸T}ٕ(0D=z ,= ( ͒ 0%{ , 7 ?(8ͬ x ͆ - r 8˸x ͏  ,-xG}r }مM 9r .>#n0͒ { = - nx ͇ ,-(-˸G,-r }ٕ?M 9.> 8ͬ ?= u+-(>͆ 0ͬ ͆ 8 ?x ͇ , 78ƀ8ƀ8ox٨!دoGOW_gɷɷ|لg{ً_zيWyىOxوG|ٔg{ٛ_zٚWyٙOx٘Gxٸyٹzٺ{ٻ|ټx٨ xx( ?}ٽ }ցr <(r 7{ = |٤g{٣_z٢Wy١Ox٠G{ ͬ ́ }x>' ͬ}ƀ/ƀo -́ }0͎-́ ͎,}l˸ 8 4 ͗ x( - 8́ - 8,́ }l8;*!͗ ! >4ͬ͗ ͗ ͬ--- ́ ,,,-xGg?+2n*8t z~,->' x' ͘}. ͆́ , ! >4,͢- o&0%,͗ }gr }؉}颋.:}8c~I$I~L*͢ٷx˸ }0G,<},-(-́ !>I0 ͗͘ o8 ͆ >' m.`1pF,t6|!wS<.z}[|%FXc~ur1}͆ٯx(<˸ 8 !~J 0.O!>s 8 =  n s͗ ͆ .n 0 ͎-́ OT0 j oD,:j !I}袋.}8c~I$I~L! >ͬ͗ I× nn ͗ = ͆ nf^VNF!DLT\I!!53!r1!͒!> x #-= o˸x͆(- }(x>8(z ,z `iÃ!>' |r |̀>)=|(DMbo˸88x(0 8> ̀x(>-{(ay( z(>. ( {>E>+|(|Dg>-|/ 0:p# ~# +>0w#,-  60#}˸}րogM| .(z = ~> x0w#xG%͇ %͇ ZJDM%͇ = _~65+~hìx-Sx9?+{Η@}|z z gZJDM0{ ,7}o˸? #yO!@9i&?  #?w#?/w#?w#!9! E9!!9~(+Fͺ!"9!(#>2*"| >"2:( Ͷ *w*6 !\$![ (ͦ( #:~CONTRMKBDLSTCAUXUSR>2i:*ˮ~0:*:(@q##pZ* :(  ~* < >26"!"""~>2""v>2>"!"ˮ(!~8>~O6~*"w(6(2(-()(6 (8 0 :(* y(~#+ (( 66 #6 #"*: y~o p .##~ͺ(.6w4._~ =*##55= *[R8*~#"= ͣ}== ͯ}͵}*#w+#~+>*~('k!0(ˮ]k!8ˮ!]~-#8~>27kˮw>O$6̃s #r$ͣ6̏ k ( (ˮ qk(ˮ ( k ˮ*O:~ ##~._q4((=ʦ==ʩ=ʬò*:4^q*##~6ͺ>2}*|(̓|( ̓6-#[RM8( G> A~#*'C! !TRUEFALSE!9N#Y~#( G~#> >    "~(kѻ(( !0 (ˮ!!>2Sz:0:*6##ww#w$w#w:  ##N#F*B>2w#w#[s#r> "~ͮ*-w#ww##> ͮÁ""~>2:ZR0 *4#4>2:ZR> *4 #4(> >22*f(/˦:G(##~++ :O x yC!ͺ Q*:G(##~._.͚f<\=<͚*##w ͮ +4 #4x >>2:G("ͮ"*nˮ*0 SZѷR8@* N#F#s#r, 0})jS\*##w+ N#FB ͮr+s>2!T]>)j)0 0= ]R!#]*^#V#N#F#^#V>2Ͱ:0:*6 #-Nw#Fwq#p#6#w#w#w"~Á>">!DM!":*B:!>(>2>">!"2"~ʰ*w#wx(9* :O *-4 #4!*4 #4 *-N#Fq#pV+^Bq#pSZѷR&* s#r$ s#rL <?*L!\  <( !\$>2>2L:>!(* \$\<(!3: [1ð\!(7"~> 2"S"Ns#FrB(Z#\: \<(?*"}K\! !*}#"}! x \* *>) 2""{_!"*nf}(HR0nf" ^VMDnfutqp*s#r*s#r"* uKB!0>' ~#fo{_"*R0RnfR0KqputsrNF( ^VNF^V*SutKqp R*R(~w~wnf ut"6#K*K*!""*NFy(* "*B0Cnf* [R*"*RS[s#r^#V""6#>O"w2x2*"!F"" &y*"*>2"*"!F"""!\*: Nr!~6go(\R*s#r_2x( s x(T]DMx(R0 U(͝O/o&9q# (!>F0#( ~ ( #]( ~ ( (#}(  i&T-a%â}ͦo*!~6o&|:2 2}:__zѯ2*|KB " z ^C User break+=  I/O Run-time error {ʹ, PC=*ͯNot enough memory Program aborted :ʎ'1!d!,B>Î)!!o&";*;!͒E *;}2E*E&}2:*:&! ͥEZ!*:&͛" }!͛!^"*:&!A!R" }20*0&́!a!z͛OEʽ!*0&!aR!A}21!*0&}21*1&͛ͺ Commands: ͛ ͛ͺ+ = Add ͛ͺ - = Subtract ͛ͺ * = Multiply ͛ͺ / = Divide ͛ͺ ^ = Exponent ͛ͺ % = Percent ͛ͺD = Display Stack ͛ͺR = Square Root ͛ͺW = Set Number of Decimals ͛ͺ$X = Exchange Top Two Levels of Stack ͛ͺ^D = Exit to CP/M ͛ͺ^X = Clear Entry ͛ D$!!!Rfzʤ#"!F*)]T)!F*!)]T),*#g#!!!vz#"!F*)]T)!F*!R)]T),*+þ#!F!)]T)!,!!,͛!*xy ""}2!}2*:ͣ!E$*:!!*!͒Eʷ$!}2͛ͺIllegal number $!,ͥ#$*&! E$!F!)]T),ͥ#*&}oEʍ)*&?R%!Í)+Rx%!F!)]T)!F!)]T),!F!)]T), S#!F!)]T),$Í)-R%!F!)]T)!F!)]T),!F!)]T), S#!F!)]T),$Í)*RF&!F!)]T)!F!)]T),!F!)]T), S#!F!)]T),$Í)/R­&!F!)]T)!F!)]T),!F!)]T), S#!F!)]T),$Í)^R'!F!)]T)!F!)]T),!F!)]T),+ Ͷ S#!F!)]T),$Í)%R‘'!F!)]T)!F!)]T),!d !F!)]T), S#!F!)]T),$Í)XR (!F!)]T),! !F!)]T)!F!)]T),!F!)]T)! ,!F!)]T),$Í)DRM(!!fzJ("!F*)]T),$*#!(Í)RR™(!F!)]T)!F!)]T),F !F!)]T),$Í)WRJ)͛ͺNumber of Decimals?  ! ͎ !:ͣ!EG)!:!!*!E+)!,"x!F!)]T),$G)͛ͺIllegal number. Í) Rn)!F!)]T),$Í)Rƒ)!*sÍ)R)k͛ ͛ͺRPN Calculator ͛ͺ'by Jon Dart ... Version 1.3 (18-Nov-84) !́!+͑!-͑!*͑!/͑!%͑!^͑!X͑!D͑!R͑!W͑!?͑!͑!͑! ͑ !́!0!9͛!.͑ !z!}2d!"x!!fzʬ*"v!F*v)]T)!*v#À*͛!#" M !f!"t!}2e ~!}2s*s&! ]OE2+*s&! ͒E+*s&.!͛ *s&!f!dP#!}2e+*s&!z ]OEʀ+*s&͛" !f:*s&e.= !f*t!"t+*s&́!͑!͑OE+*t!E+͛!"! "!" !f*t!*t!R"t+͛!" *e&E**d&Eʬ* !͑!͑OEO*t!E͛!"! "!" !f*t!*t!R"tÛ+͛!" *e&E**d&