diff --git a/k&r/04-funcs-and-prog-struct/04-calc.c b/k&r/04-funcs-and-prog-struct/04-calc.c index b564b2f..895bb98 100644 --- a/k&r/04-funcs-and-prog-struct/04-calc.c +++ b/k&r/04-funcs-and-prog-struct/04-calc.c @@ -4,31 +4,55 @@ #define printerr(format, ...) printf("error: " format "\n", ##__VA_ARGS__) +int stack_len(void); void push(double x); double pop(void); -int stack_len(void); +double peek(void); +void clear(void); + +/* --------- PROMPT FORMATS */ +#define PROMPT_F ">> " +#define POP_PRINT_F "pop -> %.8g\n" +#define PEEK_PRINT_F "peek -> %.8g\n" +#define EMPTY_F "empty\n" /* --------- ERROR MESSAGES */ #define ZERODIV_ERR "zero divisor" +#define FULL_STACK_ERR "stack full, can't push %g" +#define EMPTY_STACK_ERR "stack empty" + +/* --------- CALCULATOR FUNCTIONS TYPES */ +/* command application */ +#define COMMAND(CMD) CMD() + +/* commutative operator */ +#define COMM_OP(OP) push(pop() OP pop()) +/* non-commutative operator */ +#define NONC_OP(OP, T, ...) \ + do { T op2 = pop(); __VA_ARGS__ push(((T) pop()) OP op2); } while (0) +/* nonzero second operand */ +#define NONZ_SND_OP if (!op2) printerr(ZERODIV_ERR); else + /* --------- CALCULATOR FUNCTIONS */ -/* commutative operator application */ -#define COMM_OP(OP) push(pop() OP pop()) -/* non-commutative operator application */ -#define NONC_OP(OP, T, ...) \ - do { T op2 = pop(); __VA_ARGS__ push(((T) pop()) OP op2); } while (0) -/* nonzero second operand operator application */ -#define NONZ_OP(OP, T) \ - NONC_OP(OP, T, if (!op2) printerr(ZERODIV_ERR); else) - #define FUNCTIONS \ X(+, COMM_OP) \ X(*, COMM_OP) \ X(-, NONC_OP, double) \ - X(/, NONZ_OP, double) \ - X(%, NONZ_OP, int) + X(/, NONC_OP, double, NONZ_SND_OP) \ + X(%, NONC_OP, int, NONZ_SND_OP) \ + X(print, COMMAND) \ + X(dup, COMMAND) \ + X(swap, COMMAND) \ + X(clear, COMMAND) +/* --------- COMMAND DEFINITIONS */ + +#define print() printf(PEEK_PRINT_F, peek()) +#define dup() push(peek()) +#define swap() \ + do { double fst, snd; snd = pop(), fst = pop(); push(snd), push(fst); } while (0) #define MAXTOKEN 100 @@ -40,11 +64,16 @@ int main() char token[MAXTOKEN + 1]; double op2; int t_len; - + + printf(PROMPT_F); while (t_len = gettoken(token, MAXTOKEN)) { - if (t_len < 0) - printf("\t%g\n", pop()); - else + if (t_len < 0) { /* newline token */ + if (stack_len()) + printf(POP_PRINT_F, pop()); + else + printf(EMPTY_F); + printf(PROMPT_F); + } else #define X(F, APPLY, ...) \ if (!strcmp(#F, token)) \ APPLY(F, ##__VA_ARGS__); \ @@ -53,7 +82,10 @@ int main() #undef X push(atof(token)); } - printf("%g\n", pop()); + if (!stack_len()) + putchar('\n'); + while (stack_len()) + printf(POP_PRINT_F, pop()); return 0; } @@ -98,14 +130,14 @@ int stack_len() return sp; } + /* 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); - + printerr(FULL_STACK_ERR, f); } /* pop: pop and return top value from stack */ @@ -113,8 +145,20 @@ double pop(void) { if (sp) return val[--sp]; - printf("error: stack empty\n"); + printerr(EMPTY_STACK_ERR); + return 0; +} + +/* peek: return top value from stack, leave stack unchanged */ +double peek(void) +{ + if (sp) + return val[sp-1]; + printerr(EMPTY_STACK_ERR); return 0.0; } - +void clear(void) +{ + sp = 0; +}