/******************************************************************************
*H* ValueStack.m {Maintain push down stack of double values } V0.0, 09-FEB-91 *
*C* V0.0 09-FEB-91 Initial version                                      --MDM *
******************************************************************************/

/* Standard C Library includes */
#import <stdio.h>   	    /* Standard I/O functions and definitions */
#import <stdlib.h>  	    /* Standard C memory allocation prototypes */

#import "ValueStack.h"	    /* ValueStack interface specification */


@implementation ValueStack


/* Private Object Wide Definitions */
#define OCnullStack 	(OTvalueStackItem *) 0



/******************************************************************************
* METHOD:- init  	    	    	    	    	    	    	      *
*   Initialize a new instance of a ValueStack class.	    	    	      *
******************************************************************************/
- init

{/* BEGIN:-init */
self = [super init];
OVstackTop = OCnullStack;
return self;
}/* END:-init */




/******************************************************************************
***                   I N S T A N C E   M E T H O D S 	    	    	    ***
******************************************************************************/

/******************************************************************************
* METHOD:- free 	    	    	    	    	    	    	      *
*   All data currently on the  ValueStack  is  poped and freed, returning the *
* allocated memory back to the system pool. 	    	    	    	      *
******************************************************************************/
- free

{   /* Local Variables */
    OTvalueStackItem *tmp_blink;

/* BEGIN free */
while (OVstackTop != OCnullStack)
    {/* Get pointer to lower stack item and free top item */
    tmp_blink = OVstackTop->blink;
    free( (char *) OVstackTop );
    OVstackTop  = tmp_blink;
    OVstackSize = 0;
    }

/* Request super class to perform its free method */
return [super free];
}/* END free */



/******************************************************************************
* METHOD:- ClearStack  	    	    	    	    	    	    	      *
*   Pop and free each element on the stack until the stack is empty.          *
******************************************************************************/
- ClearStack

{   /* Local Variables */
    OTvalueStackItem  *tmp_blink;

/* BEGIN ClearStack */
while ( OVstackTop )
    {/* Stack is not empty, free top item */
    tmp_blink  = OVstackTop->blink;
    free ( (char *) OVstackTop );
    OVstackTop = tmp_blink;
    }

OVstackSize = 0;
return self;
}/* END ClearStack */



/******************************************************************************
* METHOD:- GetSize  	    	    	    	    	    	    	      *
*   Return the current number of items in the Value Stack.  	    	      *
******************************************************************************/
- (unsigned long) GetSize

{/* BEGIN GetSize */
return OVstackSize;
}/* END GetSize */



/******************************************************************************
* METHOD:- Peek     	    	    	    	    	    	    	      *
*   Return the value on the top  of  the  stack  without removing it from the *
* stack.    	    	    	    	    	    	    	    	      *
******************************************************************************/
- Peek: (double *) value

{/* BEGIN Peek */
if ( OVstackTop )
    {/* The stack is not empty return top stack value */
    *value = OVstackTop->value;
    return self;
    }
else
    {/* Report illegal reference to standard error */
#ifdef DEBUG
    fprintf(stderr, "ValueStack: Peek on empty stack returning 0.0\n");
#endif
    *value = 0.0;
    return nil;
    }
}/* END Peek */



/******************************************************************************
* METHOD:- Pop     	    	    	    	    	    	    	      *
*   Return the value on the top of the stack and free top stack item.	      *
******************************************************************************/
- Pop: (double *) value

{   /* Local Variables */
    OTvalueStackItem  *tmp_blink;

/* BEGIN Pop */
if ( OVstackTop )
    {/* Stack is not empty, free top item and return top value */
    *value = OVstackTop->value;
    tmp_blink = OVstackTop->blink;
    free ( (char *) OVstackTop );
    OVstackTop = tmp_blink;
    OVstackSize--;
    return self;    	/* successful status */
    }

else
    {/* Stack is empty report error, return 0.0 */
#ifdef DEBUG
    fprintf(stderr, "ValueStack: Pop on empty stack returning 0.0\n");
#endif
    *value = 0.0;
    return nil;	    	/* failure status */
    }
}/* END Pop */



/******************************************************************************
* METHOD:- Push     	    	    	    	    	    	    	      *
*   Push a double float value  on  the  stack.   We allocate a new stack item *
* setting its value field to  the supplied value and its blink field to point *
* to the current stack top.  If a new stack item cannot be allocated an error *
* message is written to stderr.	    	    	    	    	    	      *
******************************************************************************/
- Push: (double) value

{   /* Local Variables */
    OTvalueStackItem  *new_item;

/* BEGIN Push */
/* Allocate a new stack item */
new_item = (OTvalueStackItem *) malloc(sizeof(OTvalueStackItem));

if ( new_item )
    {/* New stack item allocated, initialize and link in new stack top */
    new_item->value = value;
    new_item->blink = OVstackTop;
    OVstackTop = new_item;
    OVstackSize++;
    return self;    
    }

else
    {/* Allocation failed, report error to stderr */
#ifdef DEBUG
    fprintf(stderr, "ValueStack: Push allocation failure\n");
#endif
    return nil;
    }
}/* END Push */



/******************************************************************************
* METHOD:- PrintStack     	    	    	    	    	    	      *
*   Print out the contents of the stack to standard output. 	    	      *
******************************************************************************/
- PrintStack

{   /* Local Variables */
    OTvalueStackItem  *trace_link;
    long    	       level;

/* BEGIN PrintStack */
if ( OVstackTop )
    {/* The stack is not empty so dump its contents */
    trace_link = OVstackTop;
    level      = 0;

    while ( trace_link )
    	{/* Not at bottom, print this item */
#ifdef DEBUG
    	printf("%2f : (%ld)\n", trace_link->value, level--);
#endif
    	trace_link = trace_link->blink;
    	}
    }

else
    {/* Stack is empty so print a message */
#ifdef DEBUG
    printf("ValueStack: stack empty\n");
#endif
    }

return self;
}/* END PrintStack */

@end /* ValueStack Implementation */
