.PAGE SIZE 58,80 .LEFT MARGIN 8 .RIGHT MARGIN 72 .SET PARAGRAPH 0,, .ENABLE TOC .AUTOPARAGRAPH .LAYOUT 1,4 .TITLE My Calculator .STYLE HEADER 4 .HEADERS ON .FIGURE 12 .c80;MY CALCULATOR .SKIP 6 .c80;16 December 1987 .SKIP 6 .c80;written by: .SKIP 2 .C80;Thomas Wolfe .C80;Jet Propulsion Laboratory .C80;Mail Stop 510/202 .C80;4800 Oak Grove Drive .C80;Pasadena, CA 91109 .C80;(818) 397-9280 .PAGE .REQUIRE "CALC.RNT" .PAGE .HEADER LEVEL INTRODUCTION My calculator program started as an exercise to learn the run-time library routine LIB$TPARSE and the C language. The functionality provided by my calculator is based on whim and a vague idea of what I wanted to accomplish. My calculator provides the capability of evaluating algebraic expression. The results may be displayed on the terminal or stored as a symbol and used in further calculations. 100 symbols may be defined with each symbol being up to 31 characters long. Symbols may be used in calculations, modified or there value displayed on the terminal. Over twenty math functions are available including pseudo random number generation. Calculator commands can be stored in files and executed. Command files allow the user to develop there own unique functions. Command files can also prompt the user for input as well as execute other command files. Integer data may be entered in octal, decimal and hexadecimal; floating-point data may be entered in decimal only. .HEADER LEVEL THE DESIGN My calculator program uses LIB$TPARSE to parse command. Action routines are called when part of a command has parsed correctly. The calculator executes parts of commands before the command is completely parsed. This means two separate types of errors are maintained. Returned values are used to determine if the command parsed correctly and the internal flag ERROR__FLAG is used to pass execution error information. For example, when a command is entered it may parse correctly but the command may not be able to execute. The returned value shows that the command parsed correctly but the error flag indicated that the command could not be executed. If I were to do it all over again I would probably parse the command completely and then execute it. However, the choice really depends on the application. Evaluation of algebraic expressions is done in two steps. The expression is first converted to a reverse Polish expression and then the expression is evaluated. Appendix B describes the algorithm used by my calculator. .PAGE .HEADER LEVEL COMMAND SUMMARY This is a brief description of the calculator commands with examples. .LITERAL Assignment: An algebraic expression is evaluated and the results is stored in a symbol. PI = 3.14159 RATE = 4.00 Expression: An algebraic expression is evaluated and the results displayed on the terminal. 123 * (SIN(76.0/PI) + COS(76.0/PI)) (RATE * 40) - 100.00 Show: Display on the current value of a symbol. SHOW PI, RATE SHOW (shows all defined symbols) Display: Change the calculator display characteristics. DISPLAY FILES,PRECISION=4 DISPLAY NOFILES Input: Prompt the user for a numeric value. INPUT/FLOAT/DEFAULT=98.6 TEMP "ENTER TEMPERATURE" INPUT/INTEGER/DEFAULT=4.00 RATE "PAY RATE" Command File: Execute command files (with a default file type of .CALC). @ABC, DEF, HIG, XYZ.CMDS Exit: Exit the currently executing command file or interactive session. EXIT Comment: Comment commands are not executed. ! THIS IS A COMMENT .END LITERAL .PAGE .HEADER LEVEL MODES OF OPERATIONS The calculator has two modes of operation, single command and interactive mode. When an error occurs, the action taken by the calculator depends the mode. .SET LEVEL 2 .HEADER LEVEL SINGLE COMMAND MODE The single command mode assumes that the calculator program has been defined as a VMS foreign command (see LOGICAL NAMES AND SYMBOLS for further information). In this mode, only the command entered on the DCL command line is executed. This allows the calculator to be part of DCL command files. The single command that is entered on the DCL command line may execute one or more command files containing many calculator commands. If an error occurs execution of the calculator is immediately terminated and control return to DCL. For example: .LITERAL $ CALC 123 + 456 $ CALC @ABC .END LITERAL .HEADER LEVEL INTERACTIVE MODE In interactive mode the calculator prompts the user for commands. If an error occurs, the interactive command is terminated and the user is prompted for the next command. If an error occurs in a command file all executing command files are terminated and the user is prompted for for the next command. Interactive mode is entered automatically if the calculator program is not defined as a VMS foreign command or if no command is entered on the DCL command line. For example: .LITERAL $ CALC Calc: A = 98.6 Calc: SHOW A A = 98.599998 Calc: EXIT .END LITERAL .SET LEVEL 1 .PAGE .HEADER LEVEL EXPRESSION COMMAND .LITERAL ---------------------------------------------------------------- Format: ---------------------------------------------------------------- Parameter: .END LITERAL .LEFT MARGIN +15 Specifies the algebraic expression to be evaluated. See ALGEBRAIC EXPRESSIONS for more information. .LEFT MARGIN -15 .LITERAL ---------------------------------------------------------------- Description: .END LITERAL .LEFT MARGIN +15 When an algebraic expression is entered, it is evaluated and the results displayed on the terminal. .LEFT MARGIN -15 .LITERAL ---------------------------------------------------------------- Examples: 1 + 2 - 3 log(ln(1.0)) MAX(LN(10.0),LOG(10.0)) * 42/SIN(0.5) .END LITERAL .PAGE .HEADER LEVEL ASSIGNMENT COMMAND .LITERAL ---------------------------------------------------------------- Format: = ---------------------------------------------------------------- Parameters: .END LITERAL .LEFT MARGIN +15 Specifies the name of the symbol to receive the results of the evaluation of the expression. .LEFT MARGIN -15 .LITERAL .END LITERAL .LEFT MARGIN +15 Specifies the algebraic expression to be evaluated. See ALGEBRAIC EXPRESSIONS for more information. .LEFT MARGIN -15 .LITERAL ---------------------------------------------------------------- Description: .END LITERAL .LEFT MARGIN +15 When an assignment command is entered the expression is evaluated and the results stored in the specified symbol. .LEFT MARGIN -15 .LITERAL ---------------------------------------------------------------- Examples: PAY_RATE = 5.50 HOURS_WORKED = 40.0 GROSS_EARNINGS = PAY_RATE * HOURS_WORKED TAKE_HOME = GROSS_EARNINGS * 0.50 .END LITERAL .PAGE .HEADER LEVEL SHOW COMMAND .LITERAL ---------------------------------------------------------------- Format: SHOW [ [[,]]] ---------------------------------------------------------------- Parameters: .END LITERAL .LEFT MARGIN +15 Specifies the name of the symbol to be displayed. .LEFT MARGIN -15 .LITERAL ---------------------------------------------------------------- Description: .END LITERAL .LEFT MARGIN +15 The SHOW command displays the value of one or more symbols on the terminal. If no symbols are specified all currently defined symbols are displayed. If the show command specifies a symbol that is currently not defined a warning message is displayed. This warning in not an error and will not cause the termination of a command file or interactive command. Parameters can be separate by commas or blanks. .LEFT MARGIN -15 .LITERAL ---------------------------------------------------------------- Examples: SHOW PAY_RATE, HOURS_WORKED, TAKE_HOME SHOW A B C SHOW .END LITERAL .PAGE .HEADER LEVEL DISPLAY COMMAND .LITERAL ---------------------------------------------------------------- Format: DISPLAY PARAMETER [[,]PARAMETER] ---------------------------------------------------------------- Parameters: FILE .END LITERAL .LEFT MARGIN +15 Specifies that commands read from command files will be displayed on the terminal before execution. An alternate form of the parameter is FILES. .LEFT MARGIN -15 .LITERAL NOFILE (default) .END LITERAL .LEFT MARGIN +15 Specifies that commands read from command files will NOT be displayed on the terminal before execution. An alternate form of the parameter is NOFILES. .LEFT MARGIN -15 .LITERAL PRECISION=[integer] .END LITERAL .LEFT MARGIN +15 Specifies the maximum number of fractional digits to be display for floating-point values. If no integer value is entered the default value of 6 is used. The precision must be an integer between 1 and 16. If a precision outside this range is entered a warning message is displayed and the precision set to the default value. This warning in not an error and will not cause the termination of a command file or interactive command. .LEFT MARGIN -15 .LITERAL ---------------------------------------------------------------- Description: .END LITERAL .LEFT MARGIN +15 ThE DISPLAY command changes the display characteristics of the calculator. Parameters can be separate by commas or blanks. .LEFT MARGIN -15 .LITERAL ---------------------------------------------------------------- Examples: DISPLAY NOFILE,PRECISION=4 DISPLAY FILE DISPLAY PRECISION=28 (will use the default) .END LITERAL .PAGE .HEADER LEVEL INPUT COMMAND .LITERAL ---------------------------------------------------------------- Format: INPUT [qualifiers] ---------------------------------------------------------------- Parameters: .END LITERAL .LEFT MARGIN +15 The name of the symbol that recieves the data entered by the user. .LEFT MARGIN -15 .LITERAL .END LITERAL .LEFT MARGIN +15 The prompt string is displayed on the terminal and the calculator waits for a response from the user. The prompt string may be up to 80 characters long and must be surrounded by quote marks ("). .LEFT MARGIN -15 .LITERAL ---------------------------------------------------------------- Qualifier: /INTEGER (default) .END LITERAL .LEFT MARGIN +15 Specifies that the users input will be converted into a integer value. This is the default data type for user input if none is specified on the input command. .LEFT MARGIN -15 .LITERAL /FLOAT .END LITERAL .LEFT MARGIN +15 Specifies that the users input will be converted into a floating-point value. .LEFT MARGIN -15 .LITERAL /DEFAULT=numeric_value .END LITERAL .LEFT MARGIN +15 Specifies that if the user enters nothing (a carriage return) the symbol will receive the default value (including the default data type). .LEFT MARGIN -15 .LITERAL ---------------------------------------------------------------- Examples: INPUT/FLOAT/DEFAULT=99 AGE "ENTER YOUR AGE:" .END LITERAL In the example, the command prompts the user for input and stores it in the symbol AGE. If the user enters a carriage return the default value 99 is stored in the symbol AGE. The data type of AGE depends on what the user enters. The symbol AGE will be forced to a floating-point value by the /FLOAT qualifier unless the default is chosen. The default value forces AGE to become the integer value 99. .PAGE .HEADER LEVEL EXIT COMMAND .LITERAL ---------------------------------------------------------------- Format: EXIT ---------------------------------------------------------------- Description: .END LITERAL .LEFT MARGIN +15 The EXIT command causes a command file or an interactive session to terminate. .LEFT MARGIN -15 .HEADER LEVEL COMMENT COMMAND .LITERAL ---------------------------------------------------------------- Format: ! ---------------------------------------------------------------- Description: .END LITERAL .LEFT MARGIN +15 Comments are not true commands and are never executed. The are provided to help document command files. The first non-blank character of a comment must be an "!". .LEFT MARGIN -15 .HEADER LEVEL DEBUG COMMAND .LITERAL ---------------------------------------------------------------- Format: DEBUG ---------------------------------------------------------------- Description: .END LITERAL .LEFT MARGIN +15 Toggles on and off the display of calculator debugging information. This command will eventually go away. .LEFT MARGIN -15 .PAGE .HEADER LEVEL ALGEBRAIC EXPRESSIONS An algebraic expression is a sequence of arithmetic operators, numeric values, symbols and functions. .SET LEVEL 2 .HEADER LEVEL DATA TYPES The calculator maintains internal numeric data in integer and floating-point form. Integer values are stored in 32 bit and can represent integers in the range -2,147,483,648 to 2,147,483,647. Floating-point values are store 64 bits and can represent values in the range 0.29E-38 to 1.7E38 with approximately 16 decimal digits of precision. .HEADER LEVEL DATA TYPE CONVERSION Functions automatically convert arguments to the correct data type(s) (which is usually floating-point) for there needs. Operators do not change the data type of operands unless integer and floating__point are mixed together. When mixed together integers are converted floating-point before an operation is performed. Conversion to a specific data type is accomplished with the functions FLT and INT. .HEADER LEVEL CONSTANTS Integer constants may be entered in octal, decimal and hexadecimal form. Octal constants must be preceeded by "%o" or "%O". Hexadecimal constants must be proceeded by "%x" or "%X". Decimal constants may be preceeded by "%d" or "%D" but it is not required. For example: .LITERAL %o7777 octal constant %xFFFF hexadecimal constant %d12345 decimal constant 12345 decimal constant .END LITERAL Floating-point constants can only be entered in decimal form. It must have a decimal point and be preceeded by at least one decimal digit (which may be zero). It may also be followed by a signed exponent preceeded by the letter "e" or "E". For example: .LITERAL 1234.5 decimal constant 0.0001 decimal constant 1232.5E10 decimal constant 0.0001e-10 decimal constant .END LITERAL .HEADER LEVEL SYMBOLS Symbols are named data structures containing numeric data. The symbol name is a string of one or more alphanumeric characters, in addition to the dollar sign ($) and the underscore (__). Symbols must start with an uppercase or lowercase A thru Z to distinguish them from numeric constants. Symbols may be of any length but only the first 31 characters will be used. Symbols may be used in algebraic expressions any were a numeric value is required. When the expression is evaluated the numeric value of the symbol is substituted in the calculation. The data type and value of a symbol may be modified with the ASSIGNMENT and INPUT commands. .HEADER LEVEL ARITHMETIC OPERATORS Symbols and numeric values may be used with operators to create more complex expressions. The operators are: .TEST PAGE 9 .LITERAL Operator Example Results - [unary] -a negative of a + [unary] +a no change in a - [binary] a-b a plus b + [binary] a+b a minus b * [binary] a*b a times b / [binary] a/b a divided by b .END LITERAL .HEADER LEVEL OPERATOR PRECEDENCE The following is the precedence used by my calculator to evaluates expressions. Operators with the highest precedence appear a the top of the list; those with the lowest appear at the bottom. .TEST PAGE 8 .LITERAL Category Operator Associativity Primary ( ) left to right Unary + - right to left Unary function right to left Binary * / left to right Binary + - left to right .END LITERAL .HEADER LEVEL MATH FUNCTIONS A variety of math function are are available in the calculator. Math functions may be used anywhere in an algebraic expression that a symbol or numeric value is used. The form of a functions is: .TEST PAGE 3 .LITERAL F(A1,A2,...An) .END LITERAL Where F is the function name and each A is a function argument. The number of arguments is function dependent. Arguments are algebraic expressions and may be as complex as needed. .SET LEVEL 3 .TEST PAGE 9 .HEADER LEVEL ABS The ABS function returns the absolute value of an integer or floating-point value. .LITERAL Format: ABS(VALUE) .END LITERAL .TEST PAGE 9 .HEADER LEVEL ACOS The ACOS function returns a value in the range zero to pi, which is the arc cosine of its radian argument. .LITERAL Format: ACOS(VALUE) .END LITERAL .TEST PAGE 9 .HEADER LEVEL ASIN The ASIN function returns a value in the range -pi/2 to pi/2, which is the arc sine of its radian argument. .LITERAL Format: ASIN(VALUE) .END LITERAL .TEST PAGE 9 .HEADER LEVEL ATAN The ATAN function returns a value in the range -pi/2 to pi/2, which is the arc tangent of its radian argument. .LITERAL Format: ATAN(VALUE) .END LITERAL .TEST PAGE 9 .HEADER LEVEL CEILING The CEILING function returns a floating-point value which is the smallest integer which is greater than or equal to its argument. .LITERAL Format: CEILING(VALUE) .END LITERAL .TEST PAGE 9 .HEADER LEVEL COS The COS function returns the cosine of its radian argument. .LITERAL Format: COS(VALUE) .END LITERAL .TEST PAGE 9 .HEADER LEVEL COSH The COSH function returns the hyperbolic cosine of its radian argument. .LITERAL Format: COSH(VALUE) .END LITERAL .TEST PAGE 9 .HEADER LEVEL EXP The EXP function returns the base e raised to the power of the argument. .LITERAL Format: EXP(VALUE) .END LITERAL .TEST PAGE 9 .HEADER LEVEL FLT The FLT function converts its argument to a floating-point value. .LITERAL Format: FLT(VALUE) .END LITERAL .TEST PAGE 9 .HEADER LEVEL FLOOR The FLOOR function returns a floating-point value which is the largest integer which is less than or equal to its argument. .LITERAL Format: FLOOR(VALUE) .END LITERAL .TEST PAGE 9 .HEADER LEVEL INT The INT function converts its argument to an integer value. .LITERAL Format: INT(VALUE) .END LITERAL .TEST PAGE 9 .HEADER LEVEL LN The LN function returns the natural logarithm of its argument which must be a positive and non-zero value. .LITERAL Format: LN(VALUE) .END LITERAL .TEST PAGE 9 .HEADER LEVEL LOG The LOG function returns the base 10 logarithm of its argument which must be a positive and non-zero value. .LITERAL Format: LOG(VALUE) .END LITERAL .TEST PAGE 9 .HEADER LEVEL POW The POW function return the first argument raised to the power of the second argument. .LITERAL Format: POW(BASE,EXP) .END LITERAL .TEST PAGE 9 .HEADER LEVEL RAND The RAND function uses a multiplicative congruential random number generator with a repeat factor (period) of 2 to the 32 power. The function must have a legal argument even though it is not used. See the SEED function for further information. .LITERAL Format: RAND(VALUE) .END LITERAL .TEST PAGE 9 .HEADER LEVEL MAX The MAX function return the maximum of two arguments. .LITERAL Format: MAX(VALUE,VALUE) .END LITERAL .TEST PAGE 9 .HEADER LEVEL MIN The MIN function return the minimum of two arguments. .LITERAL Format: MIN(VALUE,VALUE) .END LITERAL .TEST PAGE 10 .HEADER LEVEL MOD The MOD function return an integer which is the remainder of the first integer argument divided by the second integer argument. .LITERAL Format: MOD(VALUE,VALUE) .END LITERAL .TEST PAGE 9 .HEADER LEVEL SEED The SEED function returns a random number exactly like the RAND function. The random number generator is reinitialized by calling SEED with the argument 1, or it can be set to a specific point by calling SEED with any number. .LITERAL Format: SEED(VALUE) .END LITERAL .TEST PAGE 9 .HEADER LEVEL SIN The SIN function returns the sine of the radian argument. .LITERAL Format: SIN(VALUE) .END LITERAL .TEST PAGE 9 .HEADER LEVEL SINH The SINH function returns the hyperbolic sine of the radian argument. .LITERAL Format: SINH(VALUE) .END LITERAL .TEST PAGE 9 .HEADER LEVEL SQRT The SQRT function returns the square root of its argument which may not be a negative value. .LITERAL Format: SQRT(VALUE) .END LITERAL .TEST PAGE 9 .HEADER LEVEL TAN The TAN function returns the tangent of the radian argument. .LITERAL Format: TAN(VALUE) .END LITERAL .TEST PAGE 9 .HEADER LEVEL TANH The TANH function returns the hyperbolic tangent of the radian argument. .LITERAL Format: TANH(VALUE) .END LITERAL .SET LEVEL 2 .SET LEVEL 1 .HEADER LEVEL POSSIBLE FUTURE IMPROVEMENTS Modify the actual calculator to be a callable interface so that it can be incorporated into other programs. For example, my editor. Rewrite the calculator in MACRO. Add more math functions. Expand the data types from integer and floating-point to include a greater number of types such as Q floating-point, complex, etc. Add special functions, operators, etc. for special data types such coordinate pairs, etc. Add the capability to store calculator results in a VMS symbol and/or logical name. This would increase the usefulness of the calculator in DCL command files. Not all errors are detected (underflow and overflow). Make sure that all errors are detected and reported. Improve the code. It is somewhat klugy (to say the least). .PAGE .HEADER LEVEL LOGICAL NAMES AND SYMBOLS The following logical name defines the calculator help library. .LITERAL $ DEFINE CALCULATOR_HELP DISK:[DIR]CALCULATOR_HELP.HLB .END LITERAL The following symbol definition is needed if the calculator is to be a VMS foreign command. .LITERAL $ CALC :== $DISK:[DIR]CALC.EXE .END LITERAL .HEADER LEVEL BUILD THE CALCULATOR FROM SOURCE CODE .LITERAL $ LIBRARY/CREATE/HELP CALC_HELP CALC_HELP $! $ MACRO CALC_TABLE.MAR $ CC CALC.C $ CC CALC_ASSIGNMENT.C $ CC CALC_COMMAND_FILE.C $ CC CALC_DISPLAY.C $ CC CALC_EVALUATION.C $ CC CALC_EXIT.C $ CC CALC_EXPRESSION.C $ CC CALC_FUNCTIONS.C $ CC CALC_HELP.C $ CC CALC_INPUT.C $ CC CALC_SHOW.C $ CC CALC_SYMBOLS.C $! $ LINK CALC, - CALC_ASSIGNMENT, - CALC_COMMAND_FILE, - CALC_DISPLAY, - CALC_EVALUATION, - CALC_EXIT, - CALC_EXPRESSION, - CALC_FUNCTIONS, - CALC_HELP, - CALC_INPUT, - CALC_SHOW, - CALC_SYMBOLS, - CALC_TABLE .END LITERAL .PAGE .APPENDIX CALCULATOR SYNTAX DIAGRAMS .REQUIRE "SYNTAX.RNO" .APPENDIX EXPRESSION EVALUATION ALGORITHM .REQUIRE "ALGORITHM.RNO"