magic/utils/stack.c

290 lines
6.8 KiB
C
Raw Normal View History

/*
* stack.c --
*
* General purpose stack manipulation routines.
*
* *********************************************************************
* * Copyright (C) 1985, 1990 Regents of the University of California. *
* * Permission to use, copy, modify, and distribute this *
* * software and its documentation for any purpose and without *
* * fee is hereby granted, provided that the above copyright *
* * notice appear in all copies. The University of California *
* * makes no representations about the suitability of this *
* * software for any purpose. It is provided "as is" without *
* * express or implied warranty. Export of this software outside *
* * of the United States of America may require an export license. *
* *********************************************************************
*/
#ifndef lint
static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/utils/stack.c,v 1.2 2010/06/24 12:37:58 tim Exp $";
#endif /* not lint */
#include <stdio.h>
#include "utils/magic.h"
#include "utils/utils.h"
#include "utils/stack.h"
#include "utils/malloc.h"
bool stackCopyStr;
/*
* ----------------------------------------------------------------------------
* StackNew --
*
* Allocate and initialize a new Stack.
*
* Results:
* Returns a pointer to a newly heap-allocated and initialized
* stack, with its growth increment set to the specified
* size (in entries).
*
* Side effects:
* None.
* ----------------------------------------------------------------------------
*/
Stack *
StackNew(sincr)
int sincr; /* Number of entries by which to grow storage area */
{
Stack *stack;
stack = (Stack *) mallocMagic((unsigned) (sizeof (Stack)));
stack->st_incr = sincr;
stack->st_body = (struct stackBody *) mallocMagic((unsigned) (stackSize(sincr)));
stack->st_ptr = stack->st_body->sb_data;
stack->st_body->sb_next = NULL;
return (stack);
}
/*
* ----------------------------------------------------------------------------
* StackFree --
*
* Deallocate a Stack.
*
* Results:
* None.
*
* Side effects:
* Deallocates all memory currently assigned to the Stack.
*
* ----------------------------------------------------------------------------
*/
void
StackFree(stack)
Stack *stack;
{
struct stackBody *stackp, *stacknext;
for (stackp = stack->st_body; stackp != NULL; stackp = stacknext)
{
stacknext = stackp->sb_next;
freeMagic((char *) stackp);
}
freeMagic((char *) stack);
}
/*
* ----------------------------------------------------------------------------
* StackPush --
*
* Push a new element on to a stack.
*
* Results:
* None.
*
* Side effects:
* The argument stack is updated to reflect the new
* item placed upon it.
*
* ----------------------------------------------------------------------------
*/
void
StackPush(arg, stack)
ClientData arg;
Stack *stack;
{
struct stackBody *bodyNew;
if (stack->st_ptr >= &stack->st_body->sb_data[stack->st_incr])
{
bodyNew = (struct stackBody *) mallocMagic((unsigned) (stackSize(stack->st_incr)));
bodyNew->sb_next = stack->st_body;
stack->st_ptr = bodyNew->sb_data;
stack->st_body = bodyNew;
}
*(stack->st_ptr++) = arg;
}
/*
* ----------------------------------------------------------------------------
* StackPop --
*
* Pop the top element from a Stack and return it.
*
* Results:
* Top element from stack.
* If the stack is already empty, returns NULL.
* Callers should probably avoid popping from an empty
* stack.
*
* Side effects:
* Updates the stack to reflect the result of popping its top.
*
* ----------------------------------------------------------------------------
*/
ClientData
StackPop(stack)
Stack *stack;
{
struct stackBody *bodyOld;
if (stackBodyEmpty(stack))
{
bodyOld = stack->st_body;
if (bodyOld->sb_next == NULL)
return ((ClientData) NULL);
stack->st_body = bodyOld->sb_next;
stack->st_ptr = &stack->st_body->sb_data[stack->st_incr];
freeMagic((char *) bodyOld);
}
return (*--(stack->st_ptr));
}
/*
* ----------------------------------------------------------------------------
* StackLook --
*
* Return the top element from a Stack, but don't pop it off.
*
* Results:
* Top element from stack.
* If the stack is already empty, returns NULL.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
ClientData
StackLook(stack)
Stack *stack;
{
struct stackBody *bodyNext;
if (stackBodyEmpty(stack))
{
bodyNext = stack->st_body->sb_next;
if (bodyNext == NULL)
return ((ClientData) NULL);
return (bodyNext->sb_data[stack->st_incr - 1]);
}
return ( *(stack->st_ptr - 1) );
}
/*
* ----------------------------------------------------------------------------
*
* StackEnum --
*
* Enumerate all elements on the stack. Call the supplied function
* for each occurrence.
*
* The supplied function is of the form:
* int func(stackItem, i, clientData)
* ClientData stackItem; Item put on the stack
* int i; Index of the item on stack
* ClientData cd; Points to whatever you want
* The function normally returns 0. The enumeration terminates if it
* returns anything else.
*
* Results:
* None.
*
* Side effects:
* None.
*
* ----------------------------------------------------------------------------
*/
void
StackEnum(stack, func, cd)
Stack * stack;
int (* func)();
ClientData cd;
{
int i, j;
struct stackBody * sb;
i=1;
for(sb=stack->st_body; sb!=(struct stackBody *) NULL; sb=sb->sb_next)
{
for(j=0; j<=stack->st_incr; j++)
{
if( &(sb->sb_data[j]) == stack->st_ptr ) return;
if((*func)(sb->sb_data[j], i, cd)) return;
i++;
}
}
}
/*
* ----------------------------------------------------------------------------
*
* StackCopy --
*
* Make a copy of a stack.
*
* Results:
* None.
*
* Side effects:
* Memory may get allocated if the copystr parameter says to copy
* strings rather than pointers to them.
* dest gets a copy of src. If dest is non-null, it gets freed.
*
* ----------------------------------------------------------------------------
*/
void
StackCopy(src, dest, copystr)
Stack * src, ** dest;
bool copystr;
{
int stackCopyFn();
stackCopyStr=copystr;
if(*dest!=(Stack *) NULL)
StackFree(*dest);
if(src==(Stack *) NULL)
*dest = src;
else
{
*dest = StackNew(src->st_incr);
StackEnum(src, stackCopyFn, (ClientData) * dest);
}
}
/*ARGSUSED*/
int
stackCopyFn(stackItem, i, cd)
ClientData stackItem;
int i;
ClientData cd;
{
if(stackCopyStr)
StackPush((ClientData) StrDup((char **) NULL, (char *)stackItem), (Stack *) cd);
else
StackPush(stackItem, (Stack *) cd);
return(0);
}