/*-----------------BEGIN A4.C---------------------------------*/ /********************************************************** * Colin D. Joye , 11/99 * * ECE 2420-001 F99 * * Engineering Programming and Applications * * Assignment #4, reverse polish calculator * * Due Nov 11, 1999 * * ANSI C standard code * ***********************************************************/ /*----------------------------------------------------* - This program is a reverse polish calculator implementing operators and commands: + - * / % = < > $ help quit exit clear list sum prod swap invert - Default stack size is SIZE = 10 - File: "a4.c" - Outfile: none - Optional command line arg: none *----------------------------------------------------*/ #include #include #include #include #include /* For PI= 4*atan(1) */ #include "stack.h" /* for push(), pop(), clear(), list()*/ #define SPACE " \t\n" /* whitespace for strtok() */ #define PI 3.14159286 /* 4*atan(1) */ typedef void(*F)(void); struct table_struct { /* control reroutes function calls*/ char *name; F f; char *desc; int control; }; char *word; /* pointer to one word from line */ /*---------------------1------------------------------------*/ double a,b; /* temporary variables */ static int i; /* for-loop counter */ /*-----------ADD----------------*/ void add( void) { push( pop() + pop() ); } /*-----------SUB---------------*/ void sub( void) { b = pop(); a = pop(); push( a - b); } /*-----------MUL---------------*/ void mul( void) { push(pop()*pop() ); } /*-----------DVD---------------*/ void dvd( void) { b = pop(); a = pop(); if(b==0){ printf("Warning: divide by zero\n"); push(a); push(b); /* push popped values back */ /* on stack if error */ return; } push( a / b); } /*-----------MOD---------------*/ void mod( void) /* Truncates to integers */ { int c,d; c = (int)pop(); d = (int)pop(); if(d==0){ printf("Warning: divide by zero\n"); return; } push(c % d); } /*-----------AND---------------*/ void and( void) { push((int)pop() & (int)pop() ); } /*-----------OR----------------*/ void or( void) { push((int)pop() | (int)pop() ); } /*-----------NOT---------------*/ void not( void) { push(~(int)pop()); } /*-----------PI---------------*/ void pi( void) { push(PI); } /*-----------LOOP---------------*/ void process(void); void loop(void) { int count; char *word = strtok( NULL, SPACE); char *line; char copy[BUFSIZ]; if( word == NULL) { printf( "Error: missing loop count after loop.\n"); return; } count = strtol( word, NULL, 10); /* skip error check */ line = word + strlen(word); /* pointer to the rest of the line */ *line = ' '; strcpy( copy, line); while( count-- > 0) { strcpy( line, copy); if( (word = strtok( line, SPACE))) { do { process(); } while( (word = strtok( NULL, SPACE))); } } } /*---------EXIT & QUIT----------*/ void quit( void) { exit(0); return; } /*------------INFO--------------*/ void info( void) { printf("\n" "/***********************************************************/\n" " * Colin D. Joye , 11/11/99 *\n" " * Villanova University *\n" " * ECE 2420-001 F99 *\n" " * Engineering Programming and Applications *\n" " * Assignment #4, Reverse Polish Calculator *\n" " * Done for: Dr. Richard Perry *\n" " * ANSI C standard code *\n" "/***********************************************************/\n" " /*----------------------------------------------------*/\n" " - This program is a reverse polish calculator \n" " - Default stack size is SIZE = 10 \n" " - File Name: a4.c stack.c stack.h \n" " - Outfile: none \n" " - Optional command line arg: none \n" " /*-----------------------------------------------------*/ \n\n"); return; } /*--------function table--------*/ void help(void); /* predeclare functions which */ void pre_assign(void); /* must go after the table */ void oplist(void); struct table_struct table[]={ {"help", help, "Lists commands and operators.\n Type \"help\" followed by an operator or command for a description.\n",0}, {"info", info, "Displays info about \"a4.c\".",0}, {"quit", quit, "Exits \"a4.c\".",0}, {"exit", quit, "Exits \"a4.c\".",0}, {"clear", clear, "Clears the stack.",0}, {"list", list, "Displays contents of stack.",0}, {"sum", sum,"Sums all elements in stack.",1}, {"prod", prod, "Takes a cumulative product of all elements in stack.",1}, {"swap", swap,"Swaps top two values.",1}, {"invert", invert,"Turns stack up-side-down.",1}, {"loop", loop,"loop Repeats command(s) \"n\" times.",1}, {"pi", pi,"Value of pi=4*arctan(1)",1}, /* {"", "", "", 0},*/ /* an extra space */ {"+", add,"Adds top two elements.", 1}, {"-", sub,"Subtracts top two elements.", 1}, {"*", mul,"Multiplies top two elements.", 1}, {"/", dvd,"Divides top two elements. Warning if divide by zero.", 1}, {"%", mod,"Mods top two elements. Warning if mod by zero.", 1}, {"=", pre_assign,"= , Assigns an element to a variable or symbol.", 1}, {"$", pre_assign, "$ , Unassigns an assigned variable from an element.", 2}, {"<", back,"Deletes top of stack.", 1}, {">", rep,"Replicates top of stack.", 1}, {"&", and,"Bitwise AND of two integers.", 1}, {"|", or,"Bitwise OR of two integers.", 1}, {"~", not,"Bitwise NOT of an integer.", 1}, {NULL, NULL, NULL, 0} }; /*------------HELP-------------*/ void help(void) /* printf's the list of operators and */ /* commands if just "help" is typed */ { int i; if((word = strtok( NULL ,SPACE))==NULL){ printf("\nOperators and Commands:\n"); for (i=0; table[i].name!=NULL; ++i){ if(i%2==0){ printf("\t%s",table[i].name); putchar('\t'); } else { printf("\t%s",table[i].name); putchar('\n'); } } printf("\n Type \"help\" followed by an operator" " or command for a description.\n"); } else oplist(); /* calls description of specified */ /* operator or command */ return; } /*---------PRE_ASSIGN-----------*/ void pre_assign(void) { int j; if((word = strtok( NULL ,SPACE))==NULL){ printf("Error: No assignment: %s\n",word); return; } for (j=0; table[j].name!=NULL; ++j){ /* determines if variable */ if(strcmp(word,table[j].name)==0){ /* to be assigned is a */ printf("Invalid variable: %s\n",word); /* command or operator */ return; } } if(strchr("+-.0123456789",word[0])!=NULL){ /* can't assign to numbers */ printf("Invalid assignment: %s\n",word); } else if(table[i].control==1) assign(); else if(table[i].control==2) unassign(); return; } /*-----------OPLIST-------------*/ void oplist(void) /* gives description of */ /*operator or command */ { for (i=0; table[i].name!=NULL; ++i){ if(strcmp(word,table[i].name)==0){ printf(" %s\n",table[i].desc); return; } } printf("Command or operator not found.\n"); return; } /*---------------------2------------------------------------*/ void process(void) /* process one word */ { char *endp; /* for strtod() */ double a; for (i=0; table[i].name!=NULL; ++i) if(strcmp(word,table[i].name)==0){ table[i].f(); /* calls function if "word" */ return; /* matches in table */ } if(strchr("+-.0123456789",word[0])==NULL) /* disregarding numbers */ use(); else{ /* must be a number */ errno = 0; a = strtod( word, &endp); if( *endp || errno) { printf( "Error: bad number: %s\n", word); if( errno) printf( "strtod(): %s\n", strerror( errno)); } else{ push( a); table[i].control=1; } } } /*---------------------3------------------------------------*/ int main( void) { char line[BUFSIZ]; /* one line of input */ table[1].f(); printf( " Type \"help\" for a list of commands" " and operators.\n> "); /* print initial prompt */ while(fgets(line,BUFSIZ,stdin)) { /* for each line... */ if((word=strtok(line,SPACE))) { /* if line is non-blank*/ do { process(); /* process each word */ } while( (word = strtok( NULL, SPACE))); printf("\n"); if(table[i].control!=0) list(); /* print the stack */ } printf( "> "); /* print another prompt */ } return 0; } #include "stack.c" /*------------------END A4.C-----------------------------------*/