1 : /*
2 : * OpenBIOS - free your system!
3 : * ( FCode tokenizer )
4 : *
5 : * stack.c - data and return stack handling for fcode tokenizer.
6 : *
7 : * This program is part of a free implementation of the IEEE 1275-1994
8 : * Standard for Boot (Initialization Configuration) Firmware.
9 : *
10 : * Copyright (C) 2001-2005 by Stefan Reinauer <stepan@openbios.org>
11 : *
12 : * This program is free software; you can redistribute it and/or modify
13 : * it under the terms of the GNU General Public License as published by
14 : * the Free Software Foundation; version 2 of the License.
15 : *
16 : * This program is distributed in the hope that it will be useful,
17 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : * GNU General Public License for more details.
20 : *
21 : * You should have received a copy of the GNU General Public License
22 : * along with this program; if not, write to the Free Software
23 : * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
24 : *
25 : */
26 :
27 : /* **************************************************************************
28 : * Modifications made in 2005 by IBM Corporation
29 : * (C) Copyright 2005 IBM Corporation. All Rights Reserved.
30 : * Modifications Author: David L. Paktor dlpaktor@us.ibm.com
31 : **************************************************************************** */
32 :
33 : #include <stdlib.h>
34 : #include <stdio.h>
35 : #include <string.h>
36 :
37 : #include "stack.h"
38 : #include "scanner.h"
39 : #include "errhandler.h"
40 :
41 : /* **************************************************************************
42 : *
43 : * Global Variables Imported
44 : * statbuf The word just read from the input stream
45 : *
46 : **************************************************************************** */
47 :
48 :
49 : /* **************************************************************************
50 : *
51 : * Global Variables Exported
52 : * dstack Pointer to current item on top of Data Stack
53 : *
54 : **************************************************************************** */
55 :
56 : long *dstack;
57 :
58 : /* **************************************************************************
59 : *
60 : * Local/Static Pointers ..... to ... -> Points to ...
61 : * startdstack Start of data-stack area -> last possible item
62 : * enddstack End of data-stack area -> past first item
63 : *
64 : *************************************************************************** */
65 :
66 : static long *startdstack;
67 : static long *enddstack;
68 :
69 : void clear_stack(void)
70 170 : {
71 170 : dstack = enddstack;
72 170 : }
73 :
74 : /* internal stack functions */
75 :
76 : void init_stack(void)
77 154 : {
78 154 : startdstack = safe_malloc(MAX_ELEMENTS*sizeof(long), "initting stack");
79 154 : enddstack = startdstack + MAX_ELEMENTS;
80 154 : dstack=enddstack;
81 154 : }
82 :
83 : /* Input Param: stat TRUE = Underflow, FALSE = Overflow */
84 : static void stackerror(bool stat)
85 14 : {
86 : /*
87 : * Because all of our stack operations are protected and
88 : * we have no risk of the dstack pointer going into
89 : * invalid territory, this error needs not be FATAL.
90 : */
91 14 : tokenization_error ( TKERROR , "stack %sflow at or near %s \n",
92 : (stat)?"under":"over" , statbuf );
93 14 : }
94 :
95 : /*
96 : * Return TRUE if the stack depth is equal to or greater than
97 : * the supplied minimum requirement. If not, print an error.
98 : */
99 : bool min_stack_depth(int mindep)
100 641 : {
101 641 : bool retval = TRUE ;
102 : long *stack_result;
103 :
104 641 : stack_result = dstack + mindep;
105 : /*
106 : * The above appears counter-intuitive. However, C compensates
107 : * for the size of the object of a pointer when it handles
108 : * address arithmetic. A more explicit expression that would
109 : * yield the same result, might look something like this:
110 : *
111 : * (long *)((int)dstack + (mindep * sizeof(long)))
112 : *
113 : * I doubt that that form would yield tighter code, or otherwise
114 : * represent any material advantage...
115 : */
116 :
117 641 : if ( stack_result > enddstack )
118 : {
119 14 : retval = FALSE;
120 14 : stackerror(TRUE);
121 : }
122 :
123 641 : return ( retval );
124 : }
125 :
126 : /*
127 : * Return TRUE if the stack has room for the supplied # of items
128 : */
129 : static bool room_on_stack_for(int newdep)
130 637 : {
131 637 : bool retval = TRUE ;
132 : long *stack_result;
133 :
134 637 : stack_result = dstack - newdep;
135 : /* See above note about "counter-intuitive" pointer address arithmetic */
136 :
137 637 : if ( stack_result < startdstack )
138 : {
139 0 : retval = FALSE;
140 0 : stackerror(FALSE);
141 : }
142 :
143 637 : return ( retval );
144 : }
145 :
146 : void dpush(long data)
147 637 : {
148 : #ifdef DEBUG_DSTACK
149 : printf("dpush: sp=%p, data=0x%lx, ", dstack, data);
150 : #endif
151 637 : if ( room_on_stack_for(1) )
152 : {
153 637 : --dstack;
154 637 : *(dstack)=data;
155 : }
156 637 : }
157 :
158 : long dpop(void)
159 637 : {
160 637 : long val = 0;
161 : #ifdef DEBUG_DSTACK
162 : printf("dpop: sp=%p, data=0x%lx, ",dstack, *dstack);
163 : #endif
164 637 : if ( min_stack_depth(1) )
165 : {
166 624 : val=*(dstack);
167 624 : dstack++;
168 : }
169 637 : return val;
170 : }
171 :
172 : long dget(void)
173 0 : {
174 0 : long val = 0;
175 0 : if ( min_stack_depth(1) )
176 : {
177 0 : val = *(dstack);
178 : }
179 0 : return val;
180 : }
181 :
182 : long stackdepth(void)
183 170 : {
184 : long depth;
185 :
186 170 : depth = enddstack - dstack;
187 : /*
188 : * Again, C's address arithmetic compensation comes into play.
189 : * See the note at min_stack_depth()
190 : *
191 : * A more explicit equivalent expression might look like this:
192 : *
193 : * (((long int)enddstack - (long int)dstack) / sizeof(long))
194 : *
195 : * I doubt any material advantage with that one either...
196 : */
197 :
198 170 : return (depth);
199 : }
200 :
201 : void swap(void)
202 3 : {
203 : long nos_temp; /* Next-On-Stack temp */
204 3 : if ( min_stack_depth(2) )
205 : {
206 2 : nos_temp = dstack[1];
207 2 : dstack[1]= dstack[0];
208 2 : dstack[0]= nos_temp;
209 : }
210 3 : }
211 :
212 : void two_swap(void)
213 1 : {
214 : long two_deep, three_deep;
215 1 : if ( min_stack_depth(4) )
216 : {
217 1 : two_deep = dstack[2];
218 1 : three_deep = dstack[3];
219 1 : dstack[2] = dstack[0];
220 1 : dstack[3] = dstack[1];
221 1 : dstack[1] = three_deep;
222 1 : dstack[0] = two_deep;
223 : }
224 1 : }
225 :
226 :
|