/*
 * rpn_2.c
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct stack_element {
    float data;
    struct stack_element *prev;
} t_stack_element;

typedef t_stack_element * t_stack;

void init_stack(t_stack * s)
{
    *s = NULL;
}

void delete_stack(t_stack * s)
{
    t_stack_element * p1, * p2;
    p1 = *s;
    while (p1 != NULL) {
        p2 = p1->prev;
        free(p1);
        p1 = p2;
    }
    *s = NULL;
}

int push(t_stack * s, float value)
{
    t_stack_element * p;
    p = malloc(sizeof(t_stack_element));
    if (p == NULL)
        return 0;
    else {
        p->data = value;
        p->prev = *s;
        *s = p;
        return 1;
    }
}

int pop(t_stack * s, float * value)
{
    t_stack_element * p;
    if (*s == NULL)
        return 0;
    else {
        p = *s;
        *value = p->data;
        *s = p->prev;
        free(p);
        return 1;
    }
}

int top_of_stack(t_stack * s, float * value)
{
    if (*s == NULL)
        return 0;
    else {
        *value = (*s)->data;
        return 1;
    }
}

int stack_size(t_stack * s)
{
    t_stack_element * p;
    int n = 0;
    p = *s;
    while (p != NULL) {
        n++;
        p = p->prev;
    }
    return n;
}

void show(t_stack * s)
{
    t_stack_element * p;
    printf("STACK: [");
    p = *s;
    while (p != NULL) {
        printf("%f ", p->data);
        p = p->prev;
    }
    printf("]\n");
}

void main()
{
    t_stack mystack;
    init_stack(&mystack);
    for (;;) {
        char cmd[64];
        float x, y;
        show(&mystack);
        printf("CMD> ");
        scanf("%s", cmd);
        if (!strcmp(cmd, "quit")) {
            delete_stack(&mystack);
            return;
        }
        else if (isdigit(cmd[0])) {
            x = atof(cmd);
            if (!push(&mystack, x))
                printf("Stack full!!\n");
        }
        else if (!strcmp(cmd, "+")) {
            if (stack_size(&mystack) < 2) {
                printf("Too few operands in stack!!\n");
            }
            else {
                pop(&mystack, &x);
                pop(&mystack, &y);
                x = x + y;
                push(&mystack, x);
            }
        }
        else if (!strcmp(cmd, "-")) {
            if (stack_size(&mystack) < 2) {
                printf("Too few operands in stack!!\n");
            }
            else {
                pop(&mystack, &x);
                pop(&mystack, &y);
                x = x - y;
                push(&mystack, x);
            }
        }
        else if (!strcmp(cmd, "*")) {
            if (stack_size(&mystack) < 2) {
                printf("Too few operands in stack!!\n");
            }
            else {
                pop(&mystack, &x);
                pop(&mystack, &y);
                x = x * y;
                push(&mystack, x);
            }
        }
        else if (!strcmp(cmd, "/")) {
            if (stack_size(&mystack) < 2) {
                printf("Too few operands in stack!!\n");
            }
            else {
                pop(&mystack, &x);
                pop(&mystack, &y);
                x = x / y;
                push(&mystack, x);
            }
        }
        else if (!strcmp(cmd, "neg")) {
            if (stack_size(&mystack) < 1) {
                printf("Too few operands in stack!!\n");
            }
            else {
                pop(&mystack, &x);
                push(&mystack, -x);
            }
        }
        else if (!strcmp(cmd, "tos")) {
            if (stack_size(&mystack) < 1) {
                printf("Too few operands in stack!!\n");
            }
            else {
                top_of_stack(&mystack, &x);
                printf("TOS: %f\n", x);
            }
        }
        else if (!strcmp(cmd, "pop")) {
            if (!pop(&mystack, &x))
                printf("Stack is empty!!\n");
        }
        else {
            printf("Invalid command\n");
        }
    }
}



