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