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