mirror of
https://github.com/RTimothyEdwards/magic.git
synced 2026-08-31 18:25:50 +02:00
Added a ARG_UNUSED macro in utils/magic.h, which produces a simple cast to void to silence the warnings. The reasons this is used as opposed to an attribute is that most compilers should support this. Besides this, the macro can be easily searched for in the future to potentially remove (where possible) the unused parameters.
291 lines
6.9 KiB
C
291 lines
6.9 KiB
C
/*
|
|
* 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;
|
|
{
|
|
ARG_UNUSED(i);
|
|
if(stackCopyStr)
|
|
StackPush((ClientData) StrDup((char **) NULL, (char *)stackItem), (Stack *) cd);
|
|
else
|
|
StackPush(stackItem, (Stack *) cd);
|
|
return(0);
|
|
}
|