sourcepawn/compiler/sctracker.c
author Scott Ehlert <ds@alliedmods.net>
Thu Apr 05 10:55:40 2007 +0000 (2007-04-05)
changeset 669 ce01c2eb020c
parent 533 b673ed1256bc
permissions -rw-r--r--
Various things:
- Fixed inline translations when using %T
- "Improved" caching of server language
- Renamed Translator::GetServerLanguageCode() to GetServerLanguage()
- Added some more comments to sm_globals.h
- Natives folder in project file mysteriously was moved inside Interfaces, so moved it back o_O
- DS hates empty if statements :o
     1 #include <malloc.h>
     2 #include <string.h>
     3 #include <assert.h>
     4 #include "sc.h"
     5 #include "sctracker.h"
     6 
     7 memuse_list_t *heapusage = NULL;
     8 memuse_list_t *stackusage = NULL;
     9 funcenum_t *firstenum = NULL;
    10 funcenum_t *lastenum = NULL;
    11 pstruct_t *firststruct = NULL;
    12 pstruct_t *laststruct = NULL;
    13 
    14 structarg_t *pstructs_getarg(pstruct_t *pstruct, const char *member)
    15 {
    16 	int i;
    17 
    18 	for (i=0; i<pstruct->argcount; i++)
    19 	{
    20 		if (strcmp(pstruct->args[i]->name, member) == 0)
    21 		{
    22 			return pstruct->args[i];
    23 		}
    24 	}
    25 
    26 	return NULL;
    27 }
    28 
    29 pstruct_t *pstructs_add(const char *name)
    30 {
    31 	pstruct_t *p = (pstruct_t *)malloc(sizeof(pstruct_t));
    32 	
    33 	memset(p, 0, sizeof(pstruct_t));
    34 	strcpy(p->name, name);
    35 	
    36 	if (!firststruct)
    37 	{
    38 		firststruct = p;
    39 		laststruct = p;
    40 	} else {
    41 		laststruct->next = p;
    42 		laststruct = p;
    43 	}
    44 
    45 	return p;
    46 }
    47 
    48 void pstructs_free()
    49 {
    50 	pstruct_t *p, *next;
    51 
    52 	p = firststruct;
    53 	while (p)
    54 	{
    55 		while (p->argcount--)
    56 		{
    57 			free(p->args[p->argcount]);
    58 		}
    59 		free(p->args);
    60 		next = p->next;
    61 		free(p);
    62 		p = next;
    63 	}
    64 	firststruct = NULL;
    65 	laststruct = NULL;
    66 }
    67 
    68 pstruct_t *pstructs_find(const char *name)
    69 {
    70 	pstruct_t *p = firststruct;
    71 
    72 	while (p)
    73 	{
    74 		if (strcmp(p->name, name) == 0)
    75 		{
    76 			return p;
    77 		}
    78 		p = p->next;
    79 	}
    80 
    81 	return NULL;
    82 }
    83 
    84 structarg_t *pstructs_addarg(pstruct_t *pstruct, const structarg_t *arg)
    85 {
    86 	structarg_t *newarg;
    87 	int i;
    88 
    89 	for (i=0; i<pstruct->argcount; i++)
    90 	{
    91 		if (strcmp(pstruct->args[i]->name, arg->name) == 0)
    92 		{
    93 			/* Don't allow dup names */
    94 			return NULL;
    95 		}
    96 	}
    97 	
    98 	newarg = (structarg_t *)malloc(sizeof(structarg_t));
    99 
   100 	memcpy(newarg, arg, sizeof(structarg_t));
   101 
   102 	if (pstruct->argcount == 0)
   103 	{
   104 		pstruct->args = (structarg_t **)malloc(sizeof(structarg_t *) * 1);
   105 	} else {
   106 		pstruct->args = (structarg_t **)realloc(
   107 							pstruct->args,
   108 							sizeof(structarg_t *) * (pstruct->argcount + 1));
   109 	}
   110 
   111 	newarg->offs = pstruct->argcount * sizeof(cell);
   112 	newarg->index = pstruct->argcount;
   113 	pstruct->args[pstruct->argcount++] = newarg;
   114 
   115 	return newarg;
   116 }
   117 
   118 void funcenums_free()
   119 {
   120 	funcenum_t *e, *next;
   121 
   122 	e = firstenum;
   123 	while (e)
   124 	{
   125 		functag_t *tag, *nexttag;
   126 		tag = e->first;
   127 		while (tag)
   128 		{
   129 			nexttag = tag->next;
   130 			free(tag);
   131 			tag = nexttag;
   132 		}
   133 		next = e->next;
   134 		free(e);
   135 		e = next;
   136 	}
   137 
   138 	firstenum = NULL;
   139 	lastenum = NULL;
   140 }
   141 
   142 funcenum_t *funcenums_find_byval(int value)
   143 {
   144 	funcenum_t *e = firstenum;
   145 
   146 	while (e)
   147 	{
   148 		if (e->value == value)
   149 		{
   150 			return e;
   151 		}
   152 		e = e->next;
   153 	}
   154 
   155 	return NULL;
   156 }
   157 
   158 funcenum_t *funcenums_add(const char *name)
   159 {
   160 	funcenum_t *e = (funcenum_t *)malloc(sizeof(funcenum_t));
   161 
   162 	memset(e, 0, sizeof(funcenum_t));
   163 
   164 	if (firstenum == NULL)
   165 	{
   166 		firstenum = e;
   167 		lastenum = e;
   168 	} else {
   169 		lastenum->next = e;
   170 		lastenum = e;
   171 	}
   172 
   173 	strcpy(e->name, name);
   174 	e->value = pc_addfunctag((char *)name);
   175 
   176 	return e;
   177 }
   178 
   179 functag_t *functags_add(funcenum_t *en, functag_t *src)
   180 {
   181 	functag_t *t = (functag_t *)malloc(sizeof(functag_t));
   182 	
   183 	memcpy(t, src, sizeof(functag_t));
   184 
   185 	t->next = NULL;
   186 
   187 	if (en->first == NULL)
   188 	{
   189 		en->first = t;
   190 		en->last = t;
   191 	} else {
   192 		en->last->next = t;
   193 		en->last = t;
   194 	}
   195 
   196 	return t;
   197 }
   198 
   199 /**
   200  * Creates a new mem usage tracker entry
   201  */
   202 void _push_memlist(memuse_list_t **head)
   203 {
   204   memuse_list_t *newlist = (memuse_list_t *)malloc(sizeof(memuse_list_t));
   205   if (*head != NULL)
   206   {
   207     newlist->list_id = (*head)->list_id + 1;
   208   } else {
   209     newlist->list_id = 0;
   210   }
   211   newlist->prev = *head;
   212   newlist->head = NULL;
   213   *head = newlist;
   214 }
   215 
   216 /**
   217  * Pops a heap list but does not free it.
   218  */
   219 memuse_list_t *_pop_save_memlist(memuse_list_t **head)
   220 {
   221   memuse_list_t *oldlist = *head;
   222   *head = (*head)->prev;
   223   return oldlist;
   224 }
   225 
   226 /**
   227  * Marks a memory usage on a memory list
   228  */
   229 int _mark_memlist(memuse_list_t *head, int type, int size)
   230 {
   231   memuse_t *use;
   232   if (type==MEMUSE_STATIC && size==0)
   233   {
   234     return 0;
   235   }
   236   use=head->head;
   237   if (use && (type==MEMUSE_STATIC) 
   238       && (use->type == type))
   239   {
   240     use->size += size;
   241   } else {
   242     use=(memuse_t *)malloc(sizeof(memuse_t));
   243     use->type=type;
   244     use->size=size;
   245     use->prev=head->head;
   246     head->head=use;
   247   }
   248   return size;
   249 }
   250 
   251 void _reset_memlist(memuse_list_t **head)
   252 {
   253   memuse_list_t *curlist = *head;
   254   memuse_list_t *tmplist;
   255   while (curlist) {
   256     memuse_t *curuse = curlist->head;
   257     memuse_t *tmpuse;
   258     while (curuse) {
   259       tmpuse = curuse->prev;
   260       free(curuse);
   261       curuse = tmpuse;
   262     }
   263     tmplist = curlist->prev;
   264     free(curlist);
   265     curlist = tmplist;
   266   }
   267   *head = NULL;
   268 }
   269 
   270 
   271 /**
   272  * Wrapper for pushing the heap list
   273  */
   274 void pushheaplist()
   275 {
   276   _push_memlist(&heapusage);
   277 }
   278 
   279 /**
   280  * Wrapper for popping and saving the heap list
   281  */
   282 memuse_list_t *popsaveheaplist()
   283 {
   284   return _pop_save_memlist(&heapusage);
   285 }
   286 
   287 /**
   288  * Wrapper for marking the heap
   289  */
   290 int markheap(int type, int size)
   291 {
   292   return _mark_memlist(heapusage, type, size);
   293 }
   294 
   295 /**
   296  * Wrapper for pushing the stack list
   297  */
   298 void pushstacklist()
   299 {
   300   _push_memlist(&stackusage);
   301 }
   302 
   303 /**
   304  * Wrapper for marking the stack
   305  */
   306 int markstack(int type, int size)
   307 {
   308   return _mark_memlist(stackusage, type, size);
   309 }
   310 
   311 /**
   312  * Generates code to free all heap allocations on a tracker
   313  */
   314 void _heap_freeusage(memuse_list_t *heap, int dofree)
   315 {
   316   memuse_t *cur=heap->head;
   317   memuse_t *tmp;
   318   while (cur)
   319   {
   320     if (cur->type == MEMUSE_STATIC)
   321 	{
   322       modheap((-1)*cur->size*sizeof(cell));
   323     } else {
   324       modheap_i();
   325     }
   326     if (dofree)
   327     {
   328       tmp=cur->prev;
   329       free(cur);
   330       cur=tmp;
   331     } else {
   332       cur=cur->prev;
   333     }
   334   }
   335   if (dofree)
   336   {
   337     heap->head=NULL;
   338   }
   339 }
   340 
   341 void _stack_genusage(memuse_list_t *stack, int dofree)
   342 {
   343   memuse_t *cur = stack->head;
   344   memuse_t *tmp;
   345   while (cur)
   346   {
   347     if (cur->type == MEMUSE_DYNAMIC)
   348 	{
   349       /* no idea yet */
   350       assert(0);
   351 	} else {
   352       modstk(cur->size * sizeof(cell));
   353 	}
   354 	if (dofree)
   355 	{
   356       tmp = cur->prev;
   357       free(cur);
   358       cur = tmp;
   359 	} else {
   360       cur = cur->prev;
   361 	}
   362   }
   363   if (dofree)
   364   {
   365     stack->head = NULL;
   366   }
   367 }
   368 
   369 /**
   370  * Pops a heap list and frees it.
   371  */
   372 void popheaplist()
   373 {
   374   memuse_list_t *oldlist;
   375   assert(heapusage!=NULL);
   376 
   377   _heap_freeusage(heapusage, 1);
   378   assert(heapusage->head==NULL);
   379 
   380   oldlist=heapusage->prev;
   381   free(heapusage);
   382   heapusage=oldlist;
   383 }
   384 
   385 void genstackfree(int stop_id)
   386 {
   387   memuse_list_t *curlist = stackusage;
   388   while (curlist && curlist->list_id > stop_id)
   389   {
   390     _stack_genusage(curlist, 0);
   391     curlist = curlist->prev;
   392   }
   393 }
   394 
   395 void genheapfree(int stop_id)
   396 {
   397   memuse_list_t *curlist = heapusage;
   398   while (curlist && curlist->list_id > stop_id)
   399   {
   400     _heap_freeusage(curlist, 0);
   401     curlist = curlist->prev;
   402   }
   403 }
   404 
   405 void popstacklist(int codegen)
   406 {
   407   memuse_list_t *oldlist;
   408   assert(stackusage != NULL);
   409 
   410   if (codegen)
   411   {
   412     _stack_genusage(stackusage, 1);
   413     assert(stackusage->head==NULL);
   414   }
   415 
   416   oldlist = stackusage->prev;
   417   free(stackusage);
   418   stackusage = oldlist;
   419 }
   420 
   421 void resetstacklist()
   422 {
   423   _reset_memlist(&stackusage);
   424 }
   425 
   426 void resetheaplist()
   427 {
   428   _reset_memlist(&heapusage);
   429 }