One of my current side projects includes a stack-based interpreter written in C for a programming language I'm designing, SSBL. Since the entire language is stack-based, I needed a way to create and store stacks. Currently there are three separate stack types:
- One that stores an array of
unsigned char
s. - One that stores an array of
unsigned short
s. - One that stores an array of
unsigned long
s.
Each individual stack can also be created with a certain in-out type, which includes:
- FIFO (first in, first out)
- FILO (first in, last out)
- LIFO (last in, first out)
- LILO (last in, last out)
Here's the code:
ssbl_stack.h
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#define STACK_SIZE 65535
#define STACK_MEMSET 0
typedef enum
{
FIFO,
FILO,
LIFO,
LILO
} SSBL_StackIO;
typedef struct
{
SSBL_StackIO m_IO;
unsigned short m_Count;
unsigned char m_Elements[STACK_SIZE];
} SSBL_StackUint8;
typedef struct
{
SSBL_StackIO m_IO;
unsigned short m_Count;
unsigned short m_Elements[STACK_SIZE];
} SSBL_StackUint16;
typedef struct
{
SSBL_StackIO m_IO;
unsigned short m_Count;
unsigned long m_Elements[STACK_SIZE];
} SSBL_StackUint32;
SSBL_StackUint8* SSBL_StackUint8Create(SSBL_StackIO io);
void SSBL_StackUint8Push(SSBL_StackUint8* stack, unsigned char element);
unsigned char SSBL_StackUint8Pop(SSBL_StackUint8* stack);
unsigned char SSBL_StackUint8Get(SSBL_StackUint8* stack, unsigned short index);
SSBL_StackUint16* SSBL_StackUint16Create(SSBL_StackIO io);
void SSBL_StackUint16Push(SSBL_StackUint16* stack, unsigned short element);
unsigned short SSBL_StackUint16Pop(SSBL_StackUint16* stack);
unsigned short SSBL_StackUint16Get(SSBL_StackUint16* stack, unsigned short index);
SSBL_StackUint32* SSBL_StackUint32Create(SSBL_StackIO io);
void SSBL_StackUint32Push(SSBL_StackUint32* stack, unsigned long element);
unsigned long SSBL_StackUint32Pop(SSBL_StackUint32* stack);
unsigned long SSBL_StackUint32Get(SSBL_StackUint32* stack, unsigned short index);
ssbl_stack.c
#include "ssbl_stack.h"
SSBL_StackUint8* SSBL_StackUint8Create(SSBL_StackIO io)
{
SSBL_StackUint8* newStack = malloc(sizeof(SSBL_StackUint8));
newStack->m_IO = io;
newStack->m_Count = 0;
memset(newStack->m_Elements, STACK_MEMSET, sizeof(newStack->m_Elements));
return newStack;
};
void SSBL_StackUint8Push(SSBL_StackUint8* stack, unsigned char element)
{
SSBL_StackUint8 tempStack = *stack;
if(tempStack.m_Count < STACK_SIZE)
{
if(tempStack.m_IO == FIFO || tempStack.m_IO == FILO)
{
for(int i = 0; i < tempStack.m_Count + 1; i++)
{
if((i + 1) < (tempStack.m_Count + 1))
{
tempStack.m_Elements[i + 1] = stack->m_Elements[i];
}
}
tempStack.m_Elements[0] = element;
tempStack.m_Count++;
*stack = tempStack;
}
else if(tempStack.m_IO == LIFO || tempStack.m_IO == LILO)
{
tempStack.m_Elements[tempStack.m_Count] = element;
tempStack.m_Count++;
*stack = tempStack;
}
}
}
unsigned char SSBL_StackUint8Pop(SSBL_StackUint8* stack)
{
SSBL_StackUint8 tempStack = *stack;
if(tempStack.m_Count > 0)
{
if(tempStack.m_IO == FIFO || tempStack.m_IO == LIFO)
{
unsigned char retVal = tempStack.m_Elements[0];
for(int i = tempStack.m_Count - 1; i >= 0; i--)
{
tempStack.m_Elements[i - 1] = stack->m_Elements[i];
}
tempStack.m_Count--;
*stack = tempStack;
return retVal;
}
else if(tempStack.m_IO == FILO || tempStack.m_IO == LILO)
{
unsigned char retVal = tempStack.m_Elements[tempStack.m_Count - 1];
tempStack.m_Elements[tempStack.m_Count - 1] = STACK_MEMSET;
tempStack.m_Count--;
*stack = tempStack;
return retVal;
}
}
return 0;
}
unsigned char SSBL_StackUint8Get(SSBL_StackUint8* stack, unsigned short index)
{
SSBL_StackUint8 tempStack = *stack;
if(index >= 0 && index < tempStack.m_Count)
{
return tempStack.m_Elements[index];
}
return 0;
}
SSBL_StackUint16* SSBL_StackUint16Create(SSBL_StackIO io)
{
SSBL_StackUint16* newStack = malloc(sizeof(SSBL_StackUint16));
newStack->m_IO = io;
newStack->m_Count = 0;
memset(newStack->m_Elements, STACK_MEMSET, sizeof(newStack->m_Elements));
return newStack;
}
void SSBL_StackUint16Push(SSBL_StackUint16* stack, unsigned short element)
{
SSBL_StackUint16 tempStack = *stack;
if(tempStack.m_Count < STACK_SIZE)
{
if(tempStack.m_IO == FIFO || tempStack.m_IO == FILO)
{
for(int i = 0; i < tempStack.m_Count + 1; i++)
{
if((i + 1) < (tempStack.m_Count + 1))
{
tempStack.m_Elements[i + 1] = stack->m_Elements[i];
}
}
tempStack.m_Elements[0] = element;
tempStack.m_Count++;
*stack = tempStack;
}
else if(tempStack.m_IO == LIFO || tempStack.m_IO == LILO)
{
tempStack.m_Elements[tempStack.m_Count] = element;
tempStack.m_Count++;
*stack = tempStack;
}
}
}
unsigned short SSBL_StackUint16Pop(SSBL_StackUint16* stack)
{
SSBL_StackUint16 tempStack = *stack;
if(tempStack.m_Count > 0)
{
if(tempStack.m_IO == FIFO || tempStack.m_IO == LIFO)
{
unsigned short retVal = tempStack.m_Elements[0];
for(int i = tempStack.m_Count - 1; i >= 0; i--)
{
tempStack.m_Elements[i - 1] = stack->m_Elements[i];
}
tempStack.m_Count--;
*stack = tempStack;
return retVal;
}
else if(tempStack.m_IO == FILO || tempStack.m_IO == LILO)
{
unsigned short retVal = tempStack.m_Elements[tempStack.m_Count - 1];
tempStack.m_Elements[tempStack.m_Count - 1] = STACK_MEMSET;
tempStack.m_Count--;
*stack = tempStack;
return retVal;
}
}
return 0;
}
unsigned short SSBL_StackUint16Get(SSBL_StackUint16* stack, unsigned short index)
{
SSBL_StackUint16 tempStack = *stack;
if(index >= 0 && index < tempStack.m_Count)
{
return tempStack.m_Elements[index];
}
return 0;
}
SSBL_StackUint32* SSBL_StackUint32Create(SSBL_StackIO io)
{
SSBL_StackUint32* newStack = malloc(sizeof(SSBL_StackUint32));
newStack->m_IO = io;
newStack->m_Count = 0;
memset(newStack->m_Elements, STACK_MEMSET, sizeof(newStack->m_Elements));
return newStack;
}
void SSBL_StackUint32Push(SSBL_StackUint32* stack, unsigned long element)
{
SSBL_StackUint32 tempStack = *stack;
if(tempStack.m_Count < STACK_SIZE)
{
if(tempStack.m_IO == FIFO || tempStack.m_IO == FILO)
{
for(int i = 0; i < tempStack.m_Count + 1; i++)
{
if((i + 1) < (tempStack.m_Count + 1))
{
tempStack.m_Elements[i + 1] = stack->m_Elements[i];
}
}
tempStack.m_Elements[0] = element;
tempStack.m_Count++;
*stack = tempStack;
}
else if(tempStack.m_IO == LIFO || tempStack.m_IO == LILO)
{
tempStack.m_Elements[tempStack.m_Count] = element;
tempStack.m_Count++;
*stack = tempStack;
}
}
}
unsigned long SSBL_StackUint32Pop(SSBL_StackUint32* stack)
{
SSBL_StackUint32 tempStack = *stack;
if(tempStack.m_Count > 0)
{
if(tempStack.m_IO == FIFO || tempStack.m_IO == LIFO)
{
unsigned long retVal = tempStack.m_Elements[0];
for(int i = tempStack.m_Count - 1; i >= 0; i--)
{
tempStack.m_Elements[i - 1] = stack->m_Elements[i];
}
tempStack.m_Count--;
*stack = tempStack;
return retVal;
}
else if(tempStack.m_IO == FILO || tempStack.m_IO == LILO)
{
unsigned long retVal = tempStack.m_Elements[tempStack.m_Count - 1];
tempStack.m_Elements[tempStack.m_Count - 1] = STACK_MEMSET;
tempStack.m_Count--;
*stack = tempStack;
return retVal;
}
}
return 0;
}
unsigned long SSBL_StackUint32Get(SSBL_StackUint32* stack, unsigned short index)
{
SSBL_StackUint32 tempStack = *stack;
if(index >= 0 && index < tempStack.m_Count)
{
return tempStack.m_Elements[index];
}
return 0;
}
test.c
#include <stdio.h> #include <conio.h> #include "util/ssbl_stack.h" int main(int argc, char** argv) { printf("Starting up\n"); printf("\n"); _getch(); SSBL_StackUint8* stack = SSBL_StackUint8Create(LILO); SSBL_StackUint8Push(stack, 44); SSBL_StackUint8Push(stack, 22); SSBL_StackUint8Push(stack, 11); printf("Stack Element=0 [get]: %d\n", SSBL_StackUint8Get(stack, 0)); printf("Stack Element=1 [get]: %d\n", SSBL_StackUint8Get(stack, 1)); printf("Stack Element=2 [get]: %d\n", SSBL_StackUint8Get(stack, 2)); printf("\n"); _getch(); printf("Stack Element [pop]: %d\n", SSBL_StackUint8Pop(stack)); printf("Stack Element [pop]: %d\n", SSBL_StackUint8Pop(stack)); printf("Stack Element [pop]: %d\n", SSBL_StackUint8Pop(stack)); printf("\n"); _getch(); return 0; }
What can be improved? Can this be genericized? Are there any bad practices? Any critical issues?
FIFO
andLILO
(orFILO
andLIFO
)? \$\endgroup\$