1 /*******************************************************************************
2 * Reverse Polish Notation calculator. *
3 * Copyright (c) 2007-2008, Samuel Fredrickson <kinghajj@gmail.com> *
4 * All rights reserved. *
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. *
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 *
25 ******************************************************************************/
27 /*******************************************************************************
28 * stack.c - implements the value stack. *
29 ******************************************************************************/
36 * Creates a new, empty stack.
38 * @return The new, empty stack.
40 RPNStack
*RPN_newStack(RPNStack
*next
)
42 RPNStack
*stack
= new(RPNStack
);
44 RPN_error("could not allocate memory for the stack.");
48 RPN_dprintf("allocated stack %p", stack
);
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
);
63 RPN_error("could not allocate memory for a stack node.");
66 RPN_dprintf("allocated node at %p to %p", node
, next
);
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
;
81 new_node
= RPN_newNode(node
->value
, RPN_copyNode(node
->next
));
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
;
97 new_stack
= RPN_newStack(stack
);
98 new_stack
->first
= RPN_copyNode(stack
->first
);
99 new_stack
->len
= stack
->len
;
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
)
115 RPN_error("tried to push to a NULL stack.");
116 RPNNode
*node
= RPN_newNode(value
, stack
->first
);
119 RPN_dprintf("pushed " RPN_VALUE_SHORT_FORMAT
" to stack", value
);
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
)
135 RPN_error("tried to pop from a NULL stack.");
136 if(RPN_canOperate(stack
, 1))
139 popped
= stack
->first
;
140 value
= popped
->value
;
142 stack
->first
= popped
->next
;
146 RPN_dprintf("poped %x from stack", popped
);
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
)
163 RPN_error("attempted to peek a NULL stack.");
165 if(RPN_canOperate(stack
, 1))
166 value
= stack
->first
->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
;
200 for(node
= stack
->first
; node
; node
= next
)
204 RPN_dprintf("freed node %p", node
);
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
)
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;
234 * @param stack The stack.
236 void RPN_printStack(RPNStack
*stack
)
241 for(node
= stack
->first
; node
; node
= node
->next
)
242 RPN_printf(RPN_VALUE_SHORT_FORMAT
", ", node
->value
);
247 * Prints a stack in more detail.
249 * @param stack The stack.
251 void RPN_printStackDetailed(RPNStack
*stack
)
256 for(node
= stack
->first
; node
; node
= node
->next
)
257 RPN_printf(RPN_VALUE_LONG_FORMAT
", ", node
->value
);