[comp.os.minix] an integer calculator, part 1 of 3

tholm@uvicctr.UUCP (Terrence W. Holm) (05/18/88)

EFTH Minix report #13  - May 1988 -  ic(1)     [part 1 of 3]


This is an implementation of an integer calculator ic(1) that we
wrote for Minix. Please consider this a public domain program.

This program IS NOT a standard Unix utility, though we feel that
it is useful enough to distribute to all of the Minix community.
(We use it mainly for base conversions while debugging low level
code.) We believe it complements "expr" and "dc".

You may want to try ic(1) on your Unix system before moving it
to Minix.

		-------------------------


There are three parts to this posting. Use the Makefile to compile
ic.h, ic.c, ic_input.c and ic_output.c. You must have installed
termcap(3). If you do not have cuserid(3) then you should comment
out its use in ic.c, (or use getlogin(3)).

A "man" page is included.



/****************************************************************/
/* Please excuse the boxes - I know I have a problem, my        */
/* psychiatrist is trying to help me. He claims that the excess */
/* characters I send through the network are slowing down the   */
/* response on his stock market reports - but, alas, I continue */
/* to broadcast meaningless '*'s throughout the world.          */
/*                                                              */
/* (Seriously, I hope that the Minix users will find the        */
/* following code both useful and readable.)                    */
/****************************************************************/



echo x - ic.1
gres '^X' '' > ic.1 << '/'
XNAME
X    ic(1)		- integer calculator
X
XSYNOPSIS
X    ic  args  ...
X
XDESCRIPTION
X    This is a simple RPN calculator, used for small calculations
X    and base conversions. All calculations are done using 32 bit
X    integers.
X
X    The standard input is usually a keyboard and the standard output 
X    requires a device with a "termcap" entry.
X
X    The program starts by interpreting any "args" as commands, where
X    the separation between arguments is considered to be the same as
X    the ENTER key. For example, "ic 692 784+". After reading the
X    arguments input is from the keyboard.
X
X    ("ic" is not a replacement for the more common Unix tool "dc".)
X
X
X    STACK OPERATIONS
X
X    The operation of this program is similar to an RPN calculator.
X    A six level stack is used. The ENTER key pushes the stack up one 
X    level. For example, "12+5" is entered as "12 ENTER 5 +".
X
X    The top two entries on the stack are exchanged by the 'x' 
X    command, and the stack is rolled down one (popped) by the
X    'p' key.
X
X    The top of the stack may be cleared by pressing the back-space
X    key. The whole stack and the registers are initialized by a 'z'.
X
X
X    NUMERIC ENTRY
X
X    The input and output bases are initially decimal, but they may
X    be changed using the 'i' and 'o' commands respectively. These
X    commands take a one character argument of 'h', 'd', 'o' or 'b'
X    to change to Hexadecimal, Decimal, Octal or Binary. While the 
X    input base is hexadecimal the letters 'a' through 'f' are used 
X    to represent the decimal values 10 through 15.
X
X    The output base may also be changed to ASCII ('a'), this causes
X    the least significant 7 bits of a value to be displayed as a
X    character. To input an ASCII value the translate ('t') command
X    may be used, it accepts one character as its argument.
X
X
X    CALCULATIONS
X
X    The arithmetic operations supported are: Negate ('.'), Add ('+'), 
X    Subtract ('-'), Multiply ('*'), Divide ('/'), and Remainder ('%').
X    The logical operations available are: Not ('~'), And ('&'), Or ('|'), 
X    and Exclusive-or ('^').
X
X    After one of these operations the last top of stack value is
X    saved. It may be restored by pressing 'l' (L).
X
X
X    SAVING RESULTS
X
X    Ten temporary registers are available. The Store ('s') command
X    followed by a digit ('0'..'9') will copy the top of the stack
X    to the specified register. The Recall ('r') command pushes the
X    contents of a register onto the top of the stack.
X
X    If the Store command is followed by a '+' preceding the digit, then
X    the top of the stack will be added to the specified "accumulator"
X    register.
X
X    Values may also be written to a file. The 'w' command writes the
X    top of the stack, using the current output base, to a file called 
X    "pad" in the current directory.  If the user does not have write 
X    access to the current directory then the file "/tmp/pad_$USER" is 
X    used as the scratch pad. The scratch pad file is erased on the
X    first use of the 'w' command within each new invocation of "ic".
X
X
X    LEAVING THE PROGRAM
X
X    The Quit ('q') key causes an immediate exit. (End of file on
X    standard input, the SIGINT and the SIGQUIT interrupts also terminate
X    the program.)
X
X    The 'm' command temporarily leaves "ic" by invoking the Minix "sh"
X    shell as a sub-process.
X
X    For help while using "ic", hit the 'h' key. If an erroneous key
X    is pressed the bell will sound.
X
X
X    COMMAND SUMMARY
X
X    Note that many commands have an alternative key-code available
X    on the extended AT keyboard. This aids entry by including most
X    commands on the right side of the keyboard.
X
X	ENTER	    Enter (push up)
X	BS (DEL)    Clear top of stack
X
X	h	    Help
X	i	    Input base  (h, d, o, b)
X	l  (PGDN)   Last top of stack
X	m	    Minix shell
X	o	    Output base (h, d, o, b, a)
X	p  (DOWN)   Pop stack (roll down)
X	q  (END)    Quit
X	r  (LEFT)   Recall (0-9)
X	s  (RIGHT)  Store [+] (0-9)
X	t	    Translate (char)
X	w  (PGUP)   Write top of stack to scratch pad
X	x  (UP)     Exchange top of stack
X	z  (HOME)   Zero all state
X
X	.	    Change sign
X	+  (+)	    Add
X	-  (-)	    Subtract
X	*	    Multiply
X	/	    Divide
X	%  (sh/5)   Remainder
X
X	~	    Not
X	&	    And
X	|	    Or
X	^	    Exclusive-or
X
X
XFILES
X    ./pad
X    /tmp/pad_$USER
/
echo x - Makefile
gres '^X' '' > Makefile << '/'
XICOBJ   = ic.s ic_input.s ic_output.s
X
X
Xic:	$(ICOBJ)
X	cc $(ICOBJ) -o ic
X	chmem =4000 ic
X
X$(ICOBJ): ic.h
X
X
Xprint:
X		pr ic.h ic.c ic_input.c ic_output.c\
X		Makefile | lpr
/
echo x - ic.h
gres '^X' '' > ic.h << '/'
X/****************************************************************/
X/*								*/
X/*	ic.h							*/
X/*								*/
X/*		Definitions for the "Integer Calculator".	*/
X/*								*/
X/****************************************************************/
X/*  origination         1988-Apr-6               T. Holm	*/
X/****************************************************************/
X
X
X
X
X/****************************************************************/
X/*								*/
X/*	ic(1)							*/
X/*								*/
X/* This is a simple RPN calculator, used for small calculations */
X/* and base conversions. All calculations are done using 32 bit */
X/* integers.							*/
X/*								*/
X/* Commands are available for stack operations, saving results, */
X/* arithmetic and logical operations, and escaping to the Minix */
X/* shell.							*/
X/*								*/
X/* The program requires termcap(3), but otherwise should run	*/
X/* under all Unix (tm) variants.				*/
X/*								*/
X/* See the ic(1) man page.					*/
X/*								*/
X/****************************************************************/
X
X
X
X
X/****************************************************************/
X/*								*/
X/*	ic (tm)		   Copyright  Terrence W. Holm  1988	*/
X/*								*/
X/* This program was written for users of the Minix operating	*/
X/* system, and in the spirit of other public domain software	*/
X/* written for said system, this source code is made available	*/
X/* at no cost to everyone.					*/
X/*								*/
X/* This program (one .h, three .c and a "man" page) may be	*/
X/* copied and/or modified subject to (1) no charge must be	*/
X/* made for distribution, other than for the medium, (2) all	*/
X/* modified sources must be clearly marked as such, (3) all	*/
X/* sources must carry this copyright.				*/
X/*								*/
X/****************************************************************/
X
X
X
X
X/****************************************************************/
X/*								*/
X/*	files							*/
X/*								*/
X/*	    ic.h		Definitions			*/
X/*	    ic.c		The main loop			*/
X/*	    ic_input.c		Character input routines	*/
X/*	    ic_output.c		Output routines			*/
X/*								*/
X/*	    ic.1		"Man" page			*/
X/*	    Makefile		For "make"			*/
X/*								*/
X/****************************************************************/
X
X
X
X
X
X
X#define   STACK_SIZE 	6		/*  Max # of levels	*/
X#define   REGISTERS	10		/*  Registers 0 to 9	*/
X
X
X#define	  LAST_WAS_ENTER    1		/*  Numeric input modes	*/
X#define	  LAST_WAS_NUMERIC  2
X#define	  LAST_WAS_FUNCTION 3
X
X
X#define   ASCII		-1		/*  Input and output	*/
X#define   BINARY  	2		/*  modes		*/
X#define   OCTAL		8
X#define	  DECIMAL	10
X#define   HEXADECIMAL	16
X
X
X#define   OK		0		/*  Return codes	*/
X#define   ERROR		1
X
X
X
X
X
X
X#define   CTRL_D	'\004'		/*  ASCII ^D		*/
X#define   BELL		'\007'		/*  ASCII bell code     */
X#define   BS		'\010'		/*  ASCII back space	*/
X#define	  ESCAPE  	'\033'		/*  ASCII escape code	*/
X#define   DEL           '\177'		/*  ASCII delete code   */
X
X
X
X
X	/*  Input escape codes generated by the	Minix console.	*/
X	/*  Format: ESC [ X. Shows character equivalent for ic.	*/
X
X#define   ESC_HOME	'H' + 0x80  	/*   z			*/
X#define   ESC_UP	'A' + 0x80  	/*   x			*/
X#define   ESC_PGUP	'V' + 0x80	/*   w			*/
X#define   ESC_LEFT	'D' + 0x80	/*   r			*/
X#define   ESC_5		'G' + 0x80	/*   %                  */
X#define   ESC_RIGHT	'C' + 0x80	/*   s			*/
X#define   ESC_END	'Y' + 0x80	/*   q			*/
X#define   ESC_DOWN	'B' + 0x80	/*   p			*/
X#define   ESC_PGDN	'U' + 0x80	/*   l			*/
X#define   ESC_PLUS	'T' + 0x80	/*   +			*/
X#define   ESC_MINUS	'S' + 0x80	/*   -			*/
X
X
X
X
X	/*  Move positions for the output display.		*/
X
X#define   STACK_COLUMN	4
X#define   STACK_LINE	7
X#define   REG_COLUMN	STACK_COLUMN+36
X#define   REG_LINE	3
X#define   STATUS_COLUMN	6
X#define   STATUS_LINE   0
X#define   WAIT_COLUMN   0
X#define   WAIT_LINE     14
X
X
X
X
X
X
Xtypedef  struct  ic_state		/*  State of int. calc.	*/
X  {
X  long int stack[ STACK_SIZE ];		/*  The stack		*/
X  long int registers[ REGISTERS ];	/*  The registers	*/
X
X  int  stack_size;			/*  Current size (>= 1)	*/
X  int  register_mask;			/*  In use bit mask	*/
X
X  long int last_tos;			/*  For 'L' command	*/
X
X  int  mode;				/*  Last key type. See	*/
X					/*  LAST_WAS_ENTER, etc	*/
X
X  int  input_base;			/*  Current i/o base,	*/
X  int  output_base;			/*  ASCII, BINARY, etc	*/
X  
X  FILE *scratch_pad;			/*  For 'w' command	*/
X  char  file_name[20];			/*  "pad" or "/tmp/pad"	*/
X  }  ic_state;
X
X
X
X
X
X
Xint   Sigint();
Xint   Process();
Xint   Enter_Numeric();
Xint   Get_Char();
Xint   Get_Base();
Xchar *getenv();
Xchar *tgetstr();
Xchar *tgoto();
Xchar *cuserid();
XFILE *fopen();
/
--------------------------------------------------------------------
               Edwin L. Froese
                  (in London for the month)

               Terrence W. Holm
                  {uw-beaver,ubc-cs}!uvicctr!sirius!tholm