mirror of
https://github.com/RTimothyEdwards/magic.git
synced 2026-08-29 01:24:51 +02:00
Initial commit at Tue Apr 25 08:41:48 EDT 2017 by tim on stravinsky
This commit is contained in:
+289
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
Reference in New Issue
Block a user