#include <stdio.h>
#include <stdlib.h>

#define BUFSIZE 20
#define TRUE     1
#define FALSE    0

struct stack_elem {
  int data;
  struct stack_elem *prev;
};

struct stack_elem *stack_top = NULL;
int stack_depth = 0;

/* x をスタックにプッシュする */
int stack_push(int x) 
{
  struct stack_elem *tmp;

  if ((tmp = 
         (struct stack_elem *)malloc(sizeof(struct stack_elem))) 
            == NULL) {
    fprintf(stderr, "Memory Error!\n");
    exit(-1);
  }
  tmp->data = x;
  tmp->prev = stack_top, stack_top = tmp;
  stack_depth++;

  return x;
}

/* スタックトップにあるデータをポップする */
int stack_pop() 
{
  struct stack_elem *tmp;
  int x;

  if (stack_top == NULL) {
    fprintf(stderr, "The Stack is Empty.\n");
    exit(-1);
  }
  x = stack_top->data;
  tmp = stack_top, stack_top = stack_top->prev;
  free(tmp);
  stack_depth--;

  return x;
}

/* スタックが空かどうか調べる関数 */
int stack_isEmpty() 
{
  return stack_depth == 0;
}

main() 
{
  char buf[BUFSIZE];
  int x, tmp;

  /* 読み込みのエラーチェックはしていない */
  printf("> ");
  while ((int)fgets(buf,BUFSIZE,stdin)!=EOF) {
    x = atoi(buf);
    switch (buf[0]) {
    case '+': /* 足し算を行う */
      if (stack_depth < 2) {
        fprintf(stderr, "Too few arguments.\n");
        break;
      }
      printf(" %d\n", stack_push(stack_pop() + stack_pop()));
      break;
    case '-': /* 引き算を行う */
      if (stack_depth < 2) {
        fprintf(stderr, "Too few arguments.\n");
        break;
      }
      printf(" %d\n", stack_push(-stack_pop() + stack_pop()));
      break;
    case '*': /* かけ算を行う */
      if (stack_depth < 2) {
        fprintf(stderr, "Too few arguments.\n");
        break;
      }
      printf(" %d\n", stack_push(stack_pop() * stack_pop()));
      break;
    case '/': /* 割り算を行う */
      if (stack_depth < 2) {
        fprintf(stderr, "Too few arguments.\n");
        break;
      }
      tmp = stack_pop();
      printf(" %d\n", stack_push(stack_pop() / tmp));
      break;
    case 'd': /* スタックトップを複製する */
      if (stack_isEmpty()) {
        fprintf(stderr, "The stack is empty.\n");
        break;
      }
      printf(" %d: duplicated.\n", 
              stack_push(stack_push(stack_pop())));
      break;
    case 'p': /* スタックトップをポップする */
      if (stack_isEmpty()) {
        fprintf(stderr, "The stack is empty.\n");
        break;
      }
      printf(" %d: popped.\n", stack_pop());
      break;
    case 'c': /* スタックをクリアする */
      while (!stack_isEmpty())
        (void)stack_pop();
      printf(" The stack cleard.\n");
      break;
    default: /* 数値はプッシュする */
      printf(" %d: pushed.\n", stack_push(x));
    } /* switch() */
    printf ("> ");
  } /* while() */

  return 0;
}
