251cced1f8
Various minor things done to project files Updated sample extension project file and updated makefile to the new unified version (more changes likely on the way) Updated regex project file and makefile --HG-- extra : convert_revision : svn%3A39bc706e-5318-0410-9160-8a85361fbb7c/trunk%401971
430 lines
7.2 KiB
C
430 lines
7.2 KiB
C
#include <malloc.h>
|
|
#include <string.h>
|
|
#include <assert.h>
|
|
#include "sc.h"
|
|
#include "sctracker.h"
|
|
|
|
memuse_list_t *heapusage = NULL;
|
|
memuse_list_t *stackusage = NULL;
|
|
funcenum_t *firstenum = NULL;
|
|
funcenum_t *lastenum = NULL;
|
|
pstruct_t *firststruct = NULL;
|
|
pstruct_t *laststruct = NULL;
|
|
|
|
structarg_t *pstructs_getarg(pstruct_t *pstruct, const char *member)
|
|
{
|
|
int i;
|
|
|
|
for (i=0; i<pstruct->argcount; i++)
|
|
{
|
|
if (strcmp(pstruct->args[i]->name, member) == 0)
|
|
{
|
|
return pstruct->args[i];
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
pstruct_t *pstructs_add(const char *name)
|
|
{
|
|
pstruct_t *p = (pstruct_t *)malloc(sizeof(pstruct_t));
|
|
|
|
memset(p, 0, sizeof(pstruct_t));
|
|
strcpy(p->name, name);
|
|
|
|
if (!firststruct)
|
|
{
|
|
firststruct = p;
|
|
laststruct = p;
|
|
} else {
|
|
laststruct->next = p;
|
|
laststruct = p;
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
void pstructs_free()
|
|
{
|
|
pstruct_t *p, *next;
|
|
|
|
p = firststruct;
|
|
while (p)
|
|
{
|
|
while (p->argcount--)
|
|
{
|
|
free(p->args[p->argcount]);
|
|
}
|
|
free(p->args);
|
|
next = p->next;
|
|
free(p);
|
|
p = next;
|
|
}
|
|
firststruct = NULL;
|
|
laststruct = NULL;
|
|
}
|
|
|
|
pstruct_t *pstructs_find(const char *name)
|
|
{
|
|
pstruct_t *p = firststruct;
|
|
|
|
while (p)
|
|
{
|
|
if (strcmp(p->name, name) == 0)
|
|
{
|
|
return p;
|
|
}
|
|
p = p->next;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
structarg_t *pstructs_addarg(pstruct_t *pstruct, const structarg_t *arg)
|
|
{
|
|
structarg_t *newarg;
|
|
int i;
|
|
|
|
for (i=0; i<pstruct->argcount; i++)
|
|
{
|
|
if (strcmp(pstruct->args[i]->name, arg->name) == 0)
|
|
{
|
|
/* Don't allow dup names */
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
newarg = (structarg_t *)malloc(sizeof(structarg_t));
|
|
|
|
memcpy(newarg, arg, sizeof(structarg_t));
|
|
|
|
if (pstruct->argcount == 0)
|
|
{
|
|
pstruct->args = (structarg_t **)malloc(sizeof(structarg_t *) * 1);
|
|
} else {
|
|
pstruct->args = (structarg_t **)realloc(
|
|
pstruct->args,
|
|
sizeof(structarg_t *) * (pstruct->argcount + 1));
|
|
}
|
|
|
|
newarg->offs = pstruct->argcount * sizeof(cell);
|
|
newarg->index = pstruct->argcount;
|
|
pstruct->args[pstruct->argcount++] = newarg;
|
|
|
|
return newarg;
|
|
}
|
|
|
|
void funcenums_free()
|
|
{
|
|
funcenum_t *e, *next;
|
|
|
|
e = firstenum;
|
|
while (e)
|
|
{
|
|
functag_t *tag, *nexttag;
|
|
tag = e->first;
|
|
while (tag)
|
|
{
|
|
nexttag = tag->next;
|
|
free(tag);
|
|
tag = nexttag;
|
|
}
|
|
next = e->next;
|
|
free(e);
|
|
e = next;
|
|
}
|
|
|
|
firstenum = NULL;
|
|
lastenum = NULL;
|
|
}
|
|
|
|
funcenum_t *funcenums_find_byval(int value)
|
|
{
|
|
funcenum_t *e = firstenum;
|
|
|
|
while (e)
|
|
{
|
|
if (e->value == value)
|
|
{
|
|
return e;
|
|
}
|
|
e = e->next;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
funcenum_t *funcenums_add(const char *name)
|
|
{
|
|
funcenum_t *e = (funcenum_t *)malloc(sizeof(funcenum_t));
|
|
|
|
memset(e, 0, sizeof(funcenum_t));
|
|
|
|
if (firstenum == NULL)
|
|
{
|
|
firstenum = e;
|
|
lastenum = e;
|
|
} else {
|
|
lastenum->next = e;
|
|
lastenum = e;
|
|
}
|
|
|
|
strcpy(e->name, name);
|
|
e->value = pc_addfunctag((char *)name);
|
|
|
|
return e;
|
|
}
|
|
|
|
functag_t *functags_add(funcenum_t *en, functag_t *src)
|
|
{
|
|
functag_t *t = (functag_t *)malloc(sizeof(functag_t));
|
|
|
|
memcpy(t, src, sizeof(functag_t));
|
|
|
|
t->next = NULL;
|
|
|
|
if (en->first == NULL)
|
|
{
|
|
en->first = t;
|
|
en->last = t;
|
|
} else {
|
|
en->last->next = t;
|
|
en->last = t;
|
|
}
|
|
|
|
return t;
|
|
}
|
|
|
|
/**
|
|
* Creates a new mem usage tracker entry
|
|
*/
|
|
void _push_memlist(memuse_list_t **head)
|
|
{
|
|
memuse_list_t *newlist = (memuse_list_t *)malloc(sizeof(memuse_list_t));
|
|
if (*head != NULL)
|
|
{
|
|
newlist->list_id = (*head)->list_id + 1;
|
|
} else {
|
|
newlist->list_id = 0;
|
|
}
|
|
newlist->prev = *head;
|
|
newlist->head = NULL;
|
|
*head = newlist;
|
|
}
|
|
|
|
/**
|
|
* Pops a heap list but does not free it.
|
|
*/
|
|
memuse_list_t *_pop_save_memlist(memuse_list_t **head)
|
|
{
|
|
memuse_list_t *oldlist = *head;
|
|
*head = (*head)->prev;
|
|
return oldlist;
|
|
}
|
|
|
|
/**
|
|
* Marks a memory usage on a memory list
|
|
*/
|
|
int _mark_memlist(memuse_list_t *head, int type, int size)
|
|
{
|
|
memuse_t *use;
|
|
if (type==MEMUSE_STATIC && size==0)
|
|
{
|
|
return 0;
|
|
}
|
|
use=head->head;
|
|
if (use && (type==MEMUSE_STATIC)
|
|
&& (use->type == type))
|
|
{
|
|
use->size += size;
|
|
} else {
|
|
use=(memuse_t *)malloc(sizeof(memuse_t));
|
|
use->type=type;
|
|
use->size=size;
|
|
use->prev=head->head;
|
|
head->head=use;
|
|
}
|
|
return size;
|
|
}
|
|
|
|
void _reset_memlist(memuse_list_t **head)
|
|
{
|
|
memuse_list_t *curlist = *head;
|
|
memuse_list_t *tmplist;
|
|
while (curlist) {
|
|
memuse_t *curuse = curlist->head;
|
|
memuse_t *tmpuse;
|
|
while (curuse) {
|
|
tmpuse = curuse->prev;
|
|
free(curuse);
|
|
curuse = tmpuse;
|
|
}
|
|
tmplist = curlist->prev;
|
|
free(curlist);
|
|
curlist = tmplist;
|
|
}
|
|
*head = NULL;
|
|
}
|
|
|
|
|
|
/**
|
|
* Wrapper for pushing the heap list
|
|
*/
|
|
void pushheaplist()
|
|
{
|
|
_push_memlist(&heapusage);
|
|
}
|
|
|
|
/**
|
|
* Wrapper for popping and saving the heap list
|
|
*/
|
|
memuse_list_t *popsaveheaplist()
|
|
{
|
|
return _pop_save_memlist(&heapusage);
|
|
}
|
|
|
|
/**
|
|
* Wrapper for marking the heap
|
|
*/
|
|
int markheap(int type, int size)
|
|
{
|
|
return _mark_memlist(heapusage, type, size);
|
|
}
|
|
|
|
/**
|
|
* Wrapper for pushing the stack list
|
|
*/
|
|
void pushstacklist()
|
|
{
|
|
_push_memlist(&stackusage);
|
|
}
|
|
|
|
/**
|
|
* Wrapper for marking the stack
|
|
*/
|
|
int markstack(int type, int size)
|
|
{
|
|
return _mark_memlist(stackusage, type, size);
|
|
}
|
|
|
|
/**
|
|
* Generates code to free all heap allocations on a tracker
|
|
*/
|
|
void _heap_freeusage(memuse_list_t *heap, int dofree)
|
|
{
|
|
memuse_t *cur=heap->head;
|
|
memuse_t *tmp;
|
|
while (cur)
|
|
{
|
|
if (cur->type == MEMUSE_STATIC)
|
|
{
|
|
modheap((-1)*cur->size*sizeof(cell));
|
|
} else {
|
|
modheap_i();
|
|
}
|
|
if (dofree)
|
|
{
|
|
tmp=cur->prev;
|
|
free(cur);
|
|
cur=tmp;
|
|
} else {
|
|
cur=cur->prev;
|
|
}
|
|
}
|
|
if (dofree)
|
|
{
|
|
heap->head=NULL;
|
|
}
|
|
}
|
|
|
|
void _stack_genusage(memuse_list_t *stack, int dofree)
|
|
{
|
|
memuse_t *cur = stack->head;
|
|
memuse_t *tmp;
|
|
while (cur)
|
|
{
|
|
if (cur->type == MEMUSE_DYNAMIC)
|
|
{
|
|
/* no idea yet */
|
|
assert(0);
|
|
} else {
|
|
modstk(cur->size * sizeof(cell));
|
|
}
|
|
if (dofree)
|
|
{
|
|
tmp = cur->prev;
|
|
free(cur);
|
|
cur = tmp;
|
|
} else {
|
|
cur = cur->prev;
|
|
}
|
|
}
|
|
if (dofree)
|
|
{
|
|
stack->head = NULL;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Pops a heap list and frees it.
|
|
*/
|
|
void popheaplist()
|
|
{
|
|
memuse_list_t *oldlist;
|
|
assert(heapusage!=NULL);
|
|
|
|
_heap_freeusage(heapusage, 1);
|
|
assert(heapusage->head==NULL);
|
|
|
|
oldlist=heapusage->prev;
|
|
free(heapusage);
|
|
heapusage=oldlist;
|
|
}
|
|
|
|
void genstackfree(int stop_id)
|
|
{
|
|
memuse_list_t *curlist = stackusage;
|
|
while (curlist && curlist->list_id > stop_id)
|
|
{
|
|
_stack_genusage(curlist, 0);
|
|
curlist = curlist->prev;
|
|
}
|
|
}
|
|
|
|
void genheapfree(int stop_id)
|
|
{
|
|
memuse_list_t *curlist = heapusage;
|
|
while (curlist && curlist->list_id > stop_id)
|
|
{
|
|
_heap_freeusage(curlist, 0);
|
|
curlist = curlist->prev;
|
|
}
|
|
}
|
|
|
|
void popstacklist(int codegen)
|
|
{
|
|
memuse_list_t *oldlist;
|
|
assert(stackusage != NULL);
|
|
|
|
if (codegen)
|
|
{
|
|
_stack_genusage(stackusage, 1);
|
|
assert(stackusage->head==NULL);
|
|
}
|
|
|
|
oldlist = stackusage->prev;
|
|
free(stackusage);
|
|
stackusage = oldlist;
|
|
}
|
|
|
|
void resetstacklist()
|
|
{
|
|
_reset_memlist(&stackusage);
|
|
}
|
|
|
|
void resetheaplist()
|
|
{
|
|
_reset_memlist(&heapusage);
|
|
}
|