Category : Assembly Language Source Code
Archive   : MSCPOPUP.ZIP
Filename : CALC.C

 
Output of file : CALC.C contained in archive : MSCPOPUP.ZIP
/* Calc.c - Pop-up calculator program.
* This program uses the functions wopen(), wclose(), wputchar(),
* wprintf(), etc. which are contained in window.c. It also uses
* one or two variables in window.c in a very un-structured manner.
* This can be attributed to a desire to "get the damn program out,"
* or to laziness; I'm not sure which. Anyway, please pay attention to
* the end, not the means.
*/

#include
#include
#include /* Defines return codes for popup */
/* functions */

#define STACKSIZ 50 /* Calculator can handle up to 50 */
/* pending operations */
#define N_OPS 12 /* # of numerical operations */
#define MAX_NUM 20 /* Max. # digits in a number */
#define YES 1
#define NO 0
#define ERR (-1)

#define ESC 27 /* IBM-PC keyboard codes: */
#define F1 0x3b00
#define F2 0x3c00
#define F3 0x3d00
#define F4 0x3e00
#define F5 0x3f00
#define F6 0x4000
#define F7 0x4100
#define F8 0x4200
#define F9 0x4300
#define F10 0x4400

extern int border_f; /* Defined in window.c; when set to 1, */
/* windowing routines allow programs to */
/* print to the entire space occupied */
/* by a window; when 0, only the space */
/* inside the border of the window may */
/* be used */

struct { /* Define the various numerical */
/* operations and their place */
/* within the hierarchy */
char key; /* Keystroke for the operation */
int priority; /* Priority of the operation */
int int_only; /* =YES if integer-only operation */
} op[N_OPS] = {
{ '=', 0, NO }, /* The "equals" key (must always be */
/* operator #0) is treated as an */
/* operator with lowest priority. */
{ '^', 7, NO }, /* Exponentiation has highest priority */
{ '*', 6, NO }, /* Multiplication, division, and */
{ '/', 6, NO }, /* modulo operation have equal */
{ '%', 6, NO }, /* priority */
{ '+', 5, NO },
{ '-', 5, NO },
{ '<', 4, NO }, /* Binary left and */
{ '>', 4, NO }, /* right shift */
{ '&', 3, NO }, /* Binary "and" operation */
{ '|', 2, NO }, /* Binary "or" operation */
{ 'X', 1, NO } /* Binary "xor" operation */
};

double f_stack[STACKSIZ]; /* Floating-point stack */
long i_stack[STACKSIZ]; /* Integer stack */
int operation[STACKSIZ]; /* For storage of pending op's */
int stack_top = 0; /* Points to top of numerical stack */
int integers = NO; /* YES if in an integer mode (hex, */
/* octal, binary input modes) */
int base = 10; /* Radix currently working in */
int decimal = NO; /* YES if a decimal pt has been entered */
int minus = NO; /* YES if minus sign has been entered */
int first_char = NO; /* YES if first character in number is */
/* being entered */
char num_buf[MAX_NUM+1]; /* Holds number while being entered */

int error = NO; /* YES if in "Error" or "Overflow" mode */

calc(x, y) /* Brings up calculator in window at */
/* specified screen coordinates */
int x, y;

{
int i, j, k;

if (wopen(x, y, x+21, y+10, 1) == ERR) /* Open window */
return(P_MAIN); /* If open failed, return to main menu */

border_f = 0; /* To write on border temporarily */
w_setxy(0, 2);
wputchar(204);
for (i=0; i<20; ++i)
wputchar(205);
wputchar(185);
border_f = 1; /* Done printing on border */

w_setxy(0, 2);
wprintf("F1 - Dec F2 - Hex\n");
wprintf("F3 - Oct F4 - Bin\n");
wprintf("F9 - CE F10 - Clear\n");
wprintf("Operators: ^ * / %%\n");
wprintf("+ - < > & | X\n");
wprintf("Alt-H for Help");

if (first_char) /* If not in the middle of entering */
/* a number */
display(); /* Display current accumulator */
else
dispbuf(); /* Display number being entered */

for (;;) {

i = getch();
if (i >= 'a' && i <= 'z')
i = i - 'a' + 'A'; /* MSC's toupper() macro and toupper() */
/* function don't handle IBM-PC exten- */
/* ded keycodes properly */

if (error) { /* If "Error" or "Overflow" */
clear(YES); /* clear accumulator, display "0.00000" */
continue;
}

if (cnv_dig(i) != ERR || i == '.' && !decimal && !integers) {
if (num_buf[0] != ' ')
continue; /* If number entry buffer is full */

for (j=0; j num_buf[j] = num_buf[j+1]; /* Shift all digits left */
num_buf[MAX_NUM-1] = i; /* Store the digit just entered */
/* at right side of buffer */

if (i == '.')
decimal = YES;

first_char = NO;
dispbuf(); /* Redisplay entry buffer */
continue;
}

if (i == '-' && !minus && first_char) {
minus = YES;
first_char = NO;
num_buf[MAX_NUM-1] = i;

dispbuf();
continue;
}

if (i == '\b') { /* Backspace */
if (num_buf[MAX_NUM-1] == '.')
decimal = NO;
else if (num_buf[MAX_NUM-1] == '-')
minus = NO;

for (j=MAX_NUM-1; j>0; --j)
num_buf[j] = num_buf[j-1];
num_buf[0] = ' ';

if (num_buf[MAX_NUM-1] == ' ')
first_char = YES;

dispbuf();
continue;
}

if (i == F1 && integers) { /* Enter floating-point mode */
if (num_buf[MAX_NUM-1] != ' ')
read_nnum(); /* Evaluate number being entered */
for (j=0; j<=stack_top; ++j)
f_stack[j] = i_stack[j];
integers = NO;
base = 10;
display();
continue;
}

if (i == F2) { /* Enter hexadecimal mode */
if (num_buf[MAX_NUM-1] != ' ')
read_nnum(); /* Evaluate number being entered */
if (!integers) {
for (j=0; j<=stack_top; ++j)
i_stack[j] = f_stack[j];
integers = YES;
}
base = 16;
display();
continue;
}

if (i == F3) { /* Enter octal mode */
if (num_buf[MAX_NUM-1] != ' ')
read_nnum(); /* Evaluate number being entered */
if (!integers) {
for (j=0; j<=stack_top; ++j)
i_stack[j] = f_stack[j];
integers = YES;
}
base = 8;
display();
continue;
}

if (i == F4) { /* Enter binary mode */
if (num_buf[MAX_NUM-1] != ' ')
read_nnum(); /* Evaluate number being entered */
if (!integers) {
for (j=0; j<=stack_top; ++j)
i_stack[j] = f_stack[j];
integers = YES;
}
base = 2;
display();
continue;
}

if (i == F9) { /* Clear entry */
new_num();
display(); /* Show 0.000 in display */
continue;
}

if (i == F10) { /* Clear all */
clear(YES);
continue;
}

if (i == ESC) { /* Exit */
wclose();
return(P_EXIT); /* Exit from popup program */
}

if (i == '\r')
i = '='; /* Return key means = */

for (j=0; j if (op[j].key == i) { /* Found the right operator */
if (!integers && op[j].int_only)
break;

if (num_buf[MAX_NUM-1] != ' ')
read_nnum(); /* Read the number that was entered */

eval(j); /* Evaluate the operation */
display();

if (j && ++stack_top >= STACKSIZ) {
w_setxy(0, 0);
wprintf("Nesting too deep. ");
error = YES;
break;
}
break;
}

if (i == 0x3100) { /* Alt-N */
wclose();
return(P_NOTE); /* Bring up notepad */
}

if (i == 0x2600) { /* Alt-L */
wclose();
return(P_CALEN);
}

if (i == 0x1e00) { /* Alt-A */
wclose();
return(P_ASCII);
}

if (i == 0x2300) { /* Alt-H */
wclose();
return(P_HELP);
}

if (i == 0x3200) { /* Alt-M */
wclose();
return(P_MAIN);
}

continue;
}
}

clear(flag) /* Clears floating-point or integer */
/* stack */
int flag; /* =YES to display zero, =NO to */
/* not display anything */
{
int i;

error = NO;
new_num();

if (integers)
i_stack[stack_top=0] = 0;
else
f_stack[stack_top=0] = 0.0;
if (flag)
display();
}

new_num() /* Clear input buffer for new number */
{
int i;

decimal = minus = NO;
first_char = YES;

for (i=0; i num_buf[i] = ' ';
num_buf[i] = '\0'; /* Terminate number-entry buffer */
}

display()
{
long l;

w_setxy(0, 0);

if (integers)
if (base == 10)
wprintf("%20ld", i_stack[stack_top]);
else if (base == 16)
wprintf("%20lx", i_stack[stack_top]);
else if (base == 8)
wprintf("%20lo", i_stack[stack_top]);
else if (base == 2)
if ((l=i_stack[stack_top]) < 0 || l > 1048575)
overflow();
else
wprintf("%20lb", i_stack[stack_top]);
else
wprintf("Bad base - %d?", base);

else
if (f_stack[stack_top] > 2147483647)
overflow();
else
wprintf("%20.6f", f_stack[stack_top]);
}

overflow()
{
wprintf(" Overflow ");
error = 1;
}

dispbuf() /* Displays number entry buffer */
{
w_setxy(0, 0);
wprintf("%s", num_buf);
}

long a_to_i(string, base) /* Converts numerical string to long */
/* integer value using given base */
char *string;
int base;

{
long num = 0;
int i;

while (i=*string++)
num = num * base + cnv_dig(i);
return(num);

}

read_nnum()
{
if (integers) {
i_stack[stack_top] = a_to_i(num_buf, base);
} else {
sscanf(num_buf, "%lf", &f_stack[stack_top]);
}
operation[stack_top] = 0; /* Clear operation out */
new_num();
}

cnv_dig(digit) /* Convert a binary, octal, decimal or */
/* hex digit from ASCII to int format */
int digit;

{
if (digit == ' ')
return(0);

if (digit >= '0' && digit <= '9')
digit -= '0';
else if (digit >= 'A' && digit <= 'F')
digit -= 'A' - 10;
else
return(ERR);

if (digit < base)
return(digit);
else
return(ERR);
}

long do_iop(); /* Performs the specified operation on */
/* two integer arguments */
double do_fop(); /* Performs the specified operation on */
/* two floating-point arguments */

eval(oper) /* Evaluate all pending operations */
/* whose priority is at or above that */
/* of the specified operation */
int oper;

{
int i, priority;

priority = op[oper].priority;

if (integers) {
while (stack_top > 0) {
if (op[operation[stack_top-1]].priority >= priority) {
i_stack[stack_top-1] = do_iop(i_stack[stack_top-1],
i_stack[stack_top], operation[stack_top-1]);
--stack_top;
} else
break;
}
} else {
while (stack_top > 0) {
if (op[operation[stack_top-1]].priority >= priority) {
f_stack[stack_top-1] = do_fop(f_stack[stack_top-1],
f_stack[stack_top], operation[stack_top-1]);
--stack_top;
} else
break;
}
}

operation[stack_top] = oper;
}

long do_iop(arg1, arg2, op) /* Perform the specified operation on */
/* two integral arguments */
long arg1, arg2;
int op;

{
switch (op) {
case 1: /* Exponentiation */
return((long)pow((double)arg1, (double)arg2));

case 2: /* Multiplication */
return(arg1 * arg2);

case 3: /* Division */
if (arg2 == 0)
return(0); /* Add better error checking later */
else
return(arg1 / arg2);

case 4: /* Modulo */
if (arg2 == 0)
return(0);
else
return(arg1 % arg2);

case 5: /* Addition */
return(arg1 + arg2);

case 6:
return(arg1 - arg2);

case 7:
return(arg1 << arg2);

case 8:
return(arg1 >> arg2);

case 9:
return(arg1 & arg2);

case 10:
return(arg1 | arg2);

case 11:
return(arg1 ^ arg2);

default:
return(arg1);
}
}

double do_fop(arg1, arg2, op) /* Perform specified operation on two */
/* floating-point arguments */
double arg1, arg2;
int op;

{
switch (op) {
case 1: /* Exponentiation */
return(pow(arg1, arg2));

case 2: /* Multiplication */
return(arg1 * arg2);

case 3: /* Division */
if (arg2 == 0.0)
return(0.0);
else
return(arg1 / arg2);

case 4: /* Modulo */
if (arg2 == 0.0)
return(0.0);
else
return((double)((long)arg1 % (long)arg2));

case 5: /* Addition */
return(arg1 + arg2);

case 6: /* Subtraction */
return(arg1 - arg2);

case 7:
return((double)((long)arg1 << (long)arg2));

case 8:
return((double)((long)arg1 >> (long)arg2));

case 9:
return((double)((long)arg1 & (long)arg2));

case 10:
return((double)((long)arg1 | (long)arg2));

case 11:
return((double)((long)arg1 ^ (long)arg2));

default:
return(arg1);
}
}


  3 Responses to “Category : Assembly Language Source Code
Archive   : MSCPOPUP.ZIP
Filename : CALC.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/