Main Page | Data Structures | File List | Data Fields | Globals

stack.c

Go to the documentation of this file.
00001 /*
00002  *                     OpenBIOS - free your system! 
00003  *                         ( FCode tokenizer )
00004  *                          
00005  *  stack.c - data and return stack handling for fcode tokenizer.
00006  *  
00007  *  This program is part of a free implementation of the IEEE 1275-1994 
00008  *  Standard for Boot (Initialization Configuration) Firmware.
00009  *
00010  *  Copyright (C) 2001-2005 by Stefan Reinauer <stepan@openbios.org>
00011  *
00012  *  This program is free software; you can redistribute it and/or modify
00013  *  it under the terms of the GNU General Public License as published by
00014  *  the Free Software Foundation; version 2 of the License.
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU General Public License for more details.
00020  *
00021  *  You should have received a copy of the GNU General Public License
00022  *  along with this program; if not, write to the Free Software
00023  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA
00024  *
00025  */
00026 
00027 /* **************************************************************************
00028  *         Modifications made in 2005 by IBM Corporation
00029  *      (C) Copyright 2005 IBM Corporation.  All Rights Reserved.
00030  *      Modifications Author:  David L. Paktor    dlpaktor@us.ibm.com
00031  **************************************************************************** */
00032 
00033 #include <stdlib.h>
00034 #include <stdio.h>
00035 #include <string.h>
00036 
00037 #include "stack.h"
00038 #include "scanner.h"
00039 #include "errhandler.h"
00040 
00041 /* **************************************************************************
00042  *
00043  *          Global Variables Imported
00044  *              statbuf          The word just read from the input stream
00045  *
00046  **************************************************************************** */
00047 
00048 
00049 /* **************************************************************************
00050  *
00051  *          Global Variables Exported
00052  *              dstack         Pointer to current item on top of Data Stack
00053  *
00054  **************************************************************************** */
00055 
00056 long *dstack;
00057 
00058 /* **************************************************************************
00059  *
00060  *      Local/Static Pointers  .....      to  ...         -> Points to ...
00061  *          startdstack         Start of data-stack area  -> last possible item
00062  *          enddstack           End of data-stack area    -> past first item
00063  *
00064  *************************************************************************** */
00065 
00066 static long *startdstack;
00067 static long *enddstack;
00068 
00069 void clear_stack(void)
00070 {
00071     dstack = enddstack;
00072 }
00073 
00074 /* internal stack functions */
00075 
00076 void init_stack(void)
00077 {
00078         startdstack = safe_malloc(MAX_ELEMENTS*sizeof(long), "initting stack");
00079         enddstack = startdstack + MAX_ELEMENTS;
00080         dstack=enddstack;
00081 }
00082 
00083 /*  Input Param:  stat   TRUE = Underflow, FALSE = Overflow   */
00084 static void stackerror(bool stat)
00085 {
00086     /*
00087      *   Because all of our stack operations are protected and
00088      *       we have no risk of the  dstack  pointer going into
00089      *       invalid territory, this error needs not be  FATAL.
00090      */
00091     tokenization_error ( TKERROR , "stack %sflow at or near  %s \n",
00092          (stat)?"under":"over" , statbuf );
00093 }
00094 
00095 /*
00096  *  Return TRUE if the stack depth is equal to or greater than
00097  *      the supplied minimum requirement.  If not, print an error.
00098  */
00099 bool min_stack_depth(int mindep)
00100 {
00101     bool retval = TRUE ;
00102     long *stack_result;
00103 
00104     stack_result = dstack + mindep;
00105     /*
00106      *  The above appears counter-intuitive.  However, C compensates
00107      *      for the size of the object of a pointer when it handles
00108      *      address arithmetic.  A more explicit expression that would
00109      *      yield the same result, might look something like this:
00110      *
00111      *        (long *)((int)dstack + (mindep * sizeof(long)))
00112      *
00113      *  I doubt that that form would yield tighter code, or otherwise
00114      *      represent any material advantage...
00115      */
00116 
00117     if ( stack_result > enddstack )
00118     {
00119         retval = FALSE;
00120         stackerror(TRUE);
00121     }
00122 
00123     return ( retval );
00124 }
00125 
00126 /*
00127  *  Return TRUE if the stack has room for the supplied # of items
00128  */
00129 static bool room_on_stack_for(int newdep)
00130 {
00131     bool retval = TRUE ;
00132     long *stack_result;
00133 
00134     stack_result = dstack - newdep;
00135     /*  See above note about "counter-intuitive" pointer address arithmetic  */
00136 
00137     if ( stack_result < startdstack )
00138     {
00139         retval = FALSE;
00140         stackerror(FALSE);
00141     }
00142 
00143     return ( retval );
00144 }
00145 
00146 void dpush(long data)
00147 {
00148 #ifdef DEBUG_DSTACK
00149         printf("dpush: sp=%p, data=0x%lx, ", dstack, data);
00150 #endif
00151         if ( room_on_stack_for(1) )
00152         {
00153             --dstack;
00154             *(dstack)=data;
00155         }
00156 }
00157 
00158 long dpop(void)
00159 {
00160         long val = 0;
00161 #ifdef DEBUG_DSTACK
00162         printf("dpop: sp=%p, data=0x%lx, ",dstack, *dstack);
00163 #endif
00164         if ( min_stack_depth(1) )
00165         {
00166             val=*(dstack);
00167             dstack++;
00168         }
00169         return val;
00170 }
00171 
00172 long dget(void)
00173 {
00174         long val = 0;
00175         if ( min_stack_depth(1) )
00176         {
00177             val = *(dstack);
00178         }
00179         return val;
00180 }
00181 
00182 long stackdepth(void)
00183 {
00184     long depth;
00185 
00186     depth = enddstack - dstack;
00187     /*
00188      *  Again, C's address arithmetic compensation comes into play.
00189      *      See the note at  min_stack_depth()
00190      *
00191      *  A more explicit equivalent expression might look like this:
00192      *
00193      *        (((long int)enddstack - (long int)dstack) / sizeof(long))
00194      *
00195      *  I doubt any material advantage with that one either...
00196      */
00197 
00198     return (depth);
00199 }
00200 
00201 void swap(void)
00202 {
00203     long nos_temp;    /*  Next-On-Stack temp  */
00204     if ( min_stack_depth(2) )
00205     {
00206         nos_temp = dstack[1];
00207         dstack[1]= dstack[0];
00208         dstack[0]= nos_temp;
00209     }
00210 }
00211 
00212 void two_swap(void)
00213 {
00214     long two_deep, three_deep;
00215     if ( min_stack_depth(4) )
00216     {
00217         two_deep   = dstack[2];
00218         three_deep = dstack[3];
00219         dstack[2]  = dstack[0];
00220         dstack[3]  = dstack[1];
00221         dstack[1]  = three_deep;
00222         dstack[0]  = two_deep;
00223     }
00224 }
00225 
00226 

Generated on Fri Aug 18 14:03:39 2006 for Toke1.0 by  doxygen 1.4.4