#include #include "c_stack.h" /* Each node in the stack is a StackNode. This has two fields -- a value and a link to the next node in the stack. If this is the last node (bottom) in the stack, its link field will be NULL. */ typedef struct stacknode { struct stacknode *link; Jval val; } StackNode; /* The stack itself is a pointer to a TrueStack, which has two fields -- the top StackNode, and the number of nodes in the stack */ typedef struct { StackNode *top; int size; } TrueStack; /* ---------------------------------------------------------------------- */ /* To create a new stack, we malloc a TrueStack, set its top to NULL and its size to zero. We then return a pointer to that TrueStack to the user, casted to a (void *) */ Stack new_stack() { TrueStack *ts; ts = (TrueStack *) malloc(sizeof(TrueStack)); ts->top = NULL; ts->size = 0; return (Stack) ts; } /* ---------------------------------------------------------------------- */ /* Free_stack(s) gets rid of all the nodes in s, and then frees up the TrueStack storage of s. It gets rid of all the nodes by calling stack_pop() until s is empty. */ free_stack(Stack s) { TrueStack *ts; while (!stack_empty(s)) (void) stack_pop(s); ts = (TrueStack *) s; free(ts); } /* ---------------------------------------------------------------------- */ /* Test to see if the stack is empty. This is true when the stack has zero elements. */ int stack_empty(Stack s) { return (stack_size(s) == 0); } /* ---------------------------------------------------------------------- */ /* Return the number of elements in the stack -- this simply returns the size of the stack. */ int stack_size(Stack s) { TrueStack *ts; ts = (TrueStack *) s; return ts->size; } /* ---------------------------------------------------------------------- */ /* Put something on the stack. To do this, you malloc a StackNode, put the value onto that StackNode, and then make that node the top of the stack. You do this by setting the node's link field to the stack's previous top, and then setting the stack's top to the node. */ stack_push(Stack s, Jval val) { StackNode *sn; TrueStack *ts; ts = (TrueStack *) s; sn = (StackNode *) malloc(sizeof(StackNode)); sn->val = val; sn->link = ts->top; ts->top = sn; ts->size++; } /* ---------------------------------------------------------------------- */ /* Take something off the stack. To do this, you save the value of the top node, and then you get rid of the top node. This is done by first setting a pointer to the top node, and then setting the stack's top to the next node in the stack. Then you free the storage of the previous top node and return the value to the user. */ Jval stack_pop(Stack s) { Jval val; StackNode *sn; TrueStack *ts; val = stack_top(s); ts = (TrueStack *) s; sn = ts->top; ts->top = sn->link; ts->size--; free(sn); return val; } /* ---------------------------------------------------------------------- */ /* Look at the top element, but don't take it off */ Jval stack_top(Stack s) { TrueStack *ts; ts = (TrueStack *) s; if (ts->top == NULL) { fprintf(stderr, "Error: Stack_top called on an empty stack\n"); exit(1); } return ts->top->val; }