/*
Copyright (C) Information Equipment co.,LTD.
All rights reserved.
Code by JaeHyuk Cho <mailto:minzkn@infoeq.com>
*/
#if !defined(__def_mzapi_source_mzalloca_c__)
#define __def_mzapi_source_mzalloca_c__ "mzalloca.c"
#include "mzalloca.h"
#if defined(__cplusplus)
# define def_mzalloca_export extern "C"
#else
# define def_mzalloca_export
#endif
struct mzalloca_node_ts { struct mzalloca_node_ts *next, **entry; };
static int __mzalloca_detect_stack_direction(void);
def_mzalloca_export size_t mzalloca_count(void);
def_mzalloca_export void *mzalloca(size_t s_size);
static volatile size_t __g_mzalloca_count = (size_t)0;
static int __mzalloca_detect_stack_direction(void)
{
static unsigned char *sg_address = (unsigned char *)0;
auto unsigned char s_stack_byte;
if(sg_address == ((unsigned char *)0)) {
sg_address = (unsigned char *)(&s_stack_byte);
return(__mzalloca_detect_stack_direction()); /* recursive call */
}
return((sg_address < ((unsigned char *)(&s_stack_byte))) ? 1 : (-1));
}
size_t mzalloca_count(void)
{
return(__g_mzalloca_count);
}
void *mzalloca(size_t s_size)
{
static struct mzalloca_node_ts *sg_node = (struct mzalloca_node_ts *)0; /* linked list node */
static int sg_type = 0; /* stack direction type */
auto struct mzalloca_node_ts *s_temp;
if(sg_type == 0) { sg_type = __mzalloca_detect_stack_direction(); }
while(sg_node != ((struct mzalloca_node_ts *)0)) {
if(((sg_type < 0) && (sg_node->entry < ((struct mzalloca_node_ts **)(&s_temp)))) ||
((sg_type > 0) && (sg_node->entry > ((struct mzalloca_node_ts **)(&s_temp))))) {
s_temp = sg_node->next;
free((void *)sg_node);
sg_node = s_temp;
__g_mzalloca_count--;
}
else break;
}
if(s_size == ((size_t)0)) {
/* DESCRIPTION: force garbage collection */
return((void *)0);
}
do {
size_t s_allocate_size;
s_allocate_size = ((size_t)sizeof(struct mzalloca_node_ts)) + s_size;
if(s_allocate_size < s_size) {
/* ASSERT: overflow allocate size */
return((void *)0);
}
s_temp = (struct mzalloca_node_ts *)malloc(s_allocate_size);
if(s_temp == ((struct mzalloca_node_ts *)0)) {
/* ASSERT: can not allocate memory */
return((void *)0);
}
}while(0);
s_temp->entry = (struct mzalloca_node_ts **)(&s_temp);
s_temp->next = sg_node;
sg_node = s_temp;
__g_mzalloca_count++;
return((void *)(&s_temp[1]));
}
#endif
/* vim: set expandtab: */
/* End of source */