Added printing of the history stack.
[rpn.git] / src / stack.c
blobff93b969d4e5f0f28218e22e0882cbc17c63fc11
1 /*******************************************************************************
2 * Reverse Polish Notation calculator. *
3 * Copyright (c) 2007-2008, Samuel Fredrickson <kinghajj@gmail.com> *
4 * All rights reserved. *
5 * *
6 * Redistribution and use in source and binary forms, with or without *
7 * modification, are permitted provided that the following conditions are met: *
8 * * Redistributions of source code must retain the above copyright *
9 * notice, this list of conditions and the following disclaimer. *
10 * * Redistributions in binary form must reproduce the above copyright *
11 * notice, this list of conditions and the following disclaimer in the *
12 * documentation and/or other materials provided with the distribution. *
13 * *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER ``AS IS'' AND ANY EXPRESS *
15 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED *
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE *
17 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY *
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES *
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR *
20 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER *
21 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT *
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY *
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH *
24 * DAMAGE. *
25 ******************************************************************************/
27 /*******************************************************************************
28 * stack.c - implements the value stack. *
29 ******************************************************************************/
31 #include "rpn.h"
32 #include <stdio.h>
33 #include <stdlib.h>
35 /**
36 * Creates a new, empty stack.
38 * @return The new, empty stack.
40 RPNStack *RPN_newStack(RPNStack *next)
42 RPNStack *stack = new(RPNStack);
43 if(!stack)
44 RPN_error("could not allocate memory for the stack.");
45 stack->first = NULL;
46 stack->next = next;
47 stack->len = 0;
48 RPN_dprintf("allocated stack %p", stack);
49 return stack;
52 /**
53 * Creates a new node.
54 * @param value The value of the node.
56 * @param next The next node in the stack.
57 * @return The new node.
59 RPNNode *RPN_newNode(RPNValue value, RPNNode *next)
61 RPNNode *node = new(RPNNode);
62 if(!node)
63 RPN_error("could not allocate memory for a stack node.");
64 node->value = value;
65 node->next = next;
66 RPN_dprintf("allocated node at %p to %p", node, next);
67 return node;
70 /**
71 * Creates a deep copy of a node.
73 * @param node The node to copy.
74 * @return A new node and its subnodes with the same values of the input node.
76 RPNNode *RPN_copyNode(RPNNode *node)
78 RPNNode *new_node = NULL;
80 if(node)
81 new_node = RPN_newNode(node->value, RPN_copyNode(node->next));
83 return new_node;
86 /**
87 * Creates a deep copy of the stack.
89 * @param stack The stack to copy.
90 * @return A new stack with new nodes with the same values of the input stack.
92 RPNStack *RPN_copyStack(RPNStack *stack)
94 RPNStack *new_stack = NULL;
96 if(stack) {
97 new_stack = RPN_newStack(stack);
98 new_stack->first = RPN_copyNode(stack->first);
99 new_stack->len = stack->len;
102 return new_stack;
106 * Pushes a value to a stack.
108 * @param stack The stack.
109 * @param value The value to push.
110 * @return true if succeeds.
112 bool RPN_push(RPNStack *stack, RPNValue value)
114 if(!stack)
115 RPN_error("tried to push to a NULL stack.");
116 RPNNode *node = RPN_newNode(value, stack->first);
117 stack->first = node;
118 stack->len++;
119 RPN_dprintf("pushed " RPN_VALUE_SHORT_FORMAT " to stack", value);
120 return true;
124 * Pops a value from a stack.
126 * @param stack The stack to pop.
127 * @return The popped value.
129 RPNValue RPN_pop(RPNStack *stack)
131 RPNNode *popped;
132 RPNValue value = 0;
134 if(!stack)
135 RPN_error("tried to pop from a NULL stack.");
136 if(RPN_canOperate(stack, 1))
138 // get node to pop
139 popped = stack->first;
140 value = popped->value;
141 // re-wire stack
142 stack->first = popped->next;
143 // free node
144 RPN_free(popped);
145 stack->len--;
146 RPN_dprintf("poped %x from stack", popped);
149 return value;
153 * Returns the topmost item of a stack.
155 * @param stack The stack.
156 * @return The topmost item of the stack.
158 RPNValue RPN_peek(RPNStack *stack)
160 RPNValue value = 0;
162 if(!stack)
163 RPN_error("attempted to peek a NULL stack.");
165 if(RPN_canOperate(stack, 1))
166 value = stack->first->value;
168 return value;
172 * Swaps the top two items of a stack.
174 * @param stack The stack.
176 void RPN_swap(RPNStack *stack)
178 RPNValue first, second;
180 if(RPN_canOperate(stack, 2))
182 first = RPN_pop(stack);
183 second = RPN_pop(stack);
184 RPN_push(stack, first);
185 RPN_push(stack, second);
190 * Frees a stack and all of its nodes.
192 * @param stack The stack to free.
194 void RPN_freeStack(RPNStack *stack)
196 RPNNode *node, *next;
198 if(stack) {
199 // free all nodes
200 for(node = stack->first; node; node = next)
202 next = node->next;
203 RPN_free(node);
204 RPN_dprintf("freed node %p", node);
207 // free the stack
208 RPN_free(stack);
209 RPN_dprintf("freed stack %p", stack);
214 * Tests if the stack has at least a certain number of items.
216 * @param stack The stack to test.
217 * @param nargs The number of required items.
218 * @return true or false.
220 bool RPN_canOperate(RPNStack *stack, unsigned int nargs)
222 if(!stack)
223 RPN_error("tried to probe a NULL stack.");
225 RPN_dprintf("probing %p\n", stack);
227 // can only operate if there are enough items in the stack
228 return stack->len >= nargs ? true : false;
232 * Prints a stack.
234 * @param stack The stack.
236 void RPN_printStack(RPNStack *stack)
238 RPNNode *node;
240 RPN_printf("[ ");
241 for(node = stack->first; node; node = node->next)
242 RPN_printf(RPN_VALUE_SHORT_FORMAT ", ", node->value);
243 RPN_printf("]");
247 * Prints a stack in more detail.
249 * @param stack The stack.
251 void RPN_printStackDetailed(RPNStack *stack)
253 RPNNode *node;
255 RPN_printf("[ ");
256 for(node = stack->first; node; node = node->next)
257 RPN_printf(RPN_VALUE_LONG_FORMAT ", ", node->value);
258 RPN_printf("]");