fungeen

1980's television with knobs displaying random computer code

#include <stdio.h> #include <stdlib.h> /* for atof() */ #include <ctype.h> #include <math.h> #include <string.h> #define MAXOP 100 /* max size of operand or operator */ #define NUMBER '0' /* signal that a number was found */ #define ALPHA '1' /* signal that a char was found */ #define POPON '2' /* signal to pop the last stack element */ #define POPOFF '3' /* signal to not pop the last stack element */ #define VARIABLE '4' /* signal that a variable was found */ int getop(char []); void push(double); double pop(void); void printstack(void); double dupstack(void); void swapstack(void); void clearstack(void); void cmd(char []); void varhandler(char []); void varmenu(void); void getinput(void); /* globals for handling built-in and user-defined variables */ char uservar = '\0'; /* variable to be defined by stdin */ int nvars; struct allvars { char name; double val; } myvars[1000] = { /* built-in variables */ 'c', 299792458.0, /* speed of light */ 'p', 3.14, /* pi */ '\0', 0.0 /* end of array */ }; /* reverse Polish calculator */ int main(void) { int i, j, op3, op4, state, type; double lastval, op2; char s[MAXOP]; varmenu(); /* print defined variables */ getinput(); /* get line of user input */ while ((type = getop(s)) != EOF ) { switch (type) { case NUMBER: printf("NUMBER returned to main\n\n"); push(atof(s)); break; case ALPHA: cmd(s); break; case VARIABLE: varhandler(s); break; case '+': push(pop() + pop()); break; case '*': push(pop() * pop()); break; case '-': op2 = pop(); push(pop() - op2); break; case '/': op2 = pop(); if (op2 != 0.0) push(pop() / op2); else printf("error: zero divisor\n"); break; case '%': op3 = pop(); /* convert double to int */ if (op3 != 0) push((op4 = pop()) % op3); /* convert double to int */ else printf("error: zero divisor\n"); break; case '?': /* print top elements of the stack */ state = POPOFF; printstack(); break; case '$': /* duplicate the top element of the stack */ state = POPOFF; push(dupstack()); break; case '@': state = POPOFF; swapstack(); break; case '#': /* clear the stack */ clearstack(); break; case 'z': /* use last value printed */ push(lastval); break; case '=': state = POPOFF; for (nvars=j=0; myvars[j].name != '\0'; ++j, ++nvars) /* get length of array */ ; ++nvars; if (uservar != '\0') { /* if user variable, define it */ myvars[nvars-1].name = uservar; myvars[nvars-1].val = pop(); myvars[nvars].name = '\0'; myvars[nvars++].val = 0.0; varmenu(); uservar = '\0'; } else printf("error: no variable to define\n"); break; case '\n': printf("NEWLINE returned to main\n"); if (state == POPOFF) { state = POPON; break; } else printf("\t%.8g\n", lastval = pop()); break; default: printf("error: unknown command \"%s\"\n", s); break; } } return 0; } #define MAXVAL 100 /* maximum depth of val stack */ int sp = 0; /* next free stack position */ double val[MAXVAL]; /* value stack */ /* push: push f onto value stack */ void push(double f) { if (sp < MAXVAL) val[sp++] = f; else printf("error: stack full, can't push %g\n", f); } /* pop: pop and return top value from stack */ double pop(void) { if (sp > 0) return val[--sp]; else { printf("error: stack empty\n"); return 0.0; } } /* global variables for getop */ int linep=0; /* position in line[] */ char *line; /* getinput: get entire line of user input */ void getinput(void) { int bytesRead; /* length of line as returned by getline() */ size_t nbytes = 1000; /* size of line */ line = (char *) malloc(nbytes + 1); bytesRead = getline(&line, &nbytes, stdin); if (bytesRead == -1) printf("error: no input received\n"); } /* getop: get next character or numeric operand */ int getop(char s[]) { int i, c; if (line[linep] == '\0') { /* if end of string, get another line */ linep = 0; getinput(); } while (line[linep] == ' ' || line[linep] == '\t') /* remove whitespace */ ++linep; s[0] = line[linep]; c = s[0]; s[1] = '\0'; printf("line[%d] = %c\ns[0] = %c\n", linep, line[linep], s[0]); while (line[linep] != '\0') { if (!isdigit(c) && !isalpha(c) && c != '.' && c != '-') { ++linep; return c; /* not a number */ } i = 0; if (isdigit(c)) { /* collect integer part */ while (isdigit(s[++i] = line[++linep])) ; } if (c == '-') { /* test '-' unary or binary */ while (isdigit(s[++i] = line[++linep])) ; if (!isdigit(s[i-1])) { /* no digits follow. '-' is binary operator */ s[i] = '\0'; return '-'; } } if (isalpha(c)) { /* test letter as command or variable */ while (isalpha(s[++i] = line[++linep])) ; s[i] = '\0'; if (i > 1) { /* string is more than one character, it's a command */ return ALPHA; } else if (i <= 1 && s[i-1] == 'z') { /* z = last value printed */ return 'z'; } else if (c != '\n') { /* single character string is variable */ uservar = s[i-1]; /* store variable letter, deal with it later */ return VARIABLE; } } if (c == '.') /* collect fraction part */ while (isdigit(s[++i] = line[++linep])) ; s[i] = '\0'; return NUMBER; } } void printstack(void) /* print the top elements of the stack */ { int i; if (sp > 0) { for (i=(sp-1); i >= 0; --i) printf("\nstack element [%d] = %8g\n", i, val[i]); } else printf("error: nothing to print\n"); } double dupstack(void) /* duplicate the top element of the stack */ { if (sp > 0) return val[sp-1]; else printf("error: nothing to duplicate\n"); } void swapstack(void) /* swap top two elements in the stack */ { int x, y; if (sp > 1) { x = val[sp-1]; y = val[sp-2]; val[sp-2] = x; val[sp-1] = y; } else printf("error: nothing to swap\n"); } void clearstack(void) /* clear the stack */ { sp = 0; val[sp] = '\0'; } void cmd(char t[]) /* available commands */ { double op2; if (strcmp(t, "sin") == 0) push(sin(pop())); else if (strcmp(t, "exp") == 0) push(exp(pop())); else if (strcmp(t, "pow") == 0) { op2 = pop(); push(pow(pop(), op2)); } else printf("error: command unknown\n"); } void varhandler(char t[]) /* deal with single-letter variables */ { int i; for (i=0; myvars[i].name != '\0'; ++i) { /* search for variable in array */ if (t[0] == myvars[i].name) { /* if variable is defined, use value */ push(myvars[i].val); break; } else uservar = t[0]; /* if variable undefined, store letter */ } } void varmenu(void) /* print defined variables */ { int r; printf("\n/** Defined Variables **/\n\n"); for (r=0; myvars[r].name != '\0'; ++r) printf("%5c = %g\n", myvars[r].name, myvars[r].val); printf("%5s = last value printed\n", "z"); }