sourcepawn/vm/sp_vm_engine.cpp
author David Anderson <dvander@alliedmods.net>
Tue Sep 19 22:26:13 2006 +0000 (2006-09-19)
changeset 67 2fae86728e54
child 93 b00ab8fec541
permissions -rw-r--r--
initial import of magical new API... FINALLY!
dvander@67
     1
#include <malloc.h>
dvander@67
     2
#include <string.h>
dvander@67
     3
#include "sp_file_headers.h"
dvander@67
     4
#include "sp_vm_types.h"
dvander@67
     5
#include "sp_vm_engine.h"
dvander@67
     6
#include "zlib/zlib.h"
dvander@67
     7
#include "sp_vm_basecontext.h"
dvander@67
     8
dvander@67
     9
using namespace SourcePawn;
dvander@67
    10
dvander@67
    11
void *SourcePawnEngine::BaseAlloc(size_t size)
dvander@67
    12
{
dvander@67
    13
	return malloc(size);
dvander@67
    14
}
dvander@67
    15
dvander@67
    16
void SourcePawnEngine::BaseFree(void *memory)
dvander@67
    17
{
dvander@67
    18
	free(memory);
dvander@67
    19
}
dvander@67
    20
dvander@67
    21
IPluginContext *SourcePawnEngine::CreateBaseContext(sp_context_t *ctx)
dvander@67
    22
{
dvander@67
    23
	return new BaseContext(ctx);
dvander@67
    24
}
dvander@67
    25
dvander@67
    26
void SourcePawnEngine::FreeBaseContext(IPluginContext *ctx)
dvander@67
    27
{
dvander@67
    28
	sp_context_t *_ctx = ctx->GetContext();
dvander@67
    29
	IVirtualMachine *vm = ctx->GetVirtualMachine();
dvander@67
    30
	
dvander@67
    31
	vm->FreeContextVars(_ctx);
dvander@67
    32
dvander@67
    33
	delete ctx;
dvander@67
    34
}
dvander@67
    35
dvander@67
    36
sp_plugin_t *_ReadPlugin(sp_file_hdr_t *hdr, uint8_t *base, sp_plugin_t *plugin, int *err)
dvander@67
    37
{
dvander@67
    38
	char *nameptr;
dvander@67
    39
	uint8_t sectnum = 0;
dvander@67
    40
	sp_file_section_t *secptr = (sp_file_section_t *)(base + sizeof(sp_file_hdr_t));
dvander@67
    41
dvander@67
    42
	memset(plugin, 0, sizeof(sp_plugin_t));
dvander@67
    43
dvander@67
    44
	plugin->base = base;
dvander@67
    45
dvander@67
    46
	while (sectnum < hdr->sections)
dvander@67
    47
	{
dvander@67
    48
		nameptr = (char *)(base + hdr->stringtab + secptr->nameoffs);
dvander@67
    49
dvander@67
    50
		if (!(plugin->pcode) && !strcmp(nameptr, ".code"))
dvander@67
    51
		{
dvander@67
    52
			sp_file_code_t *cod = (sp_file_code_t *)(base + secptr->dataoffs);
dvander@67
    53
			plugin->pcode = base + secptr->dataoffs + cod->code;
dvander@67
    54
			plugin->pcode_size = cod->codesize;
dvander@67
    55
			plugin->flags = cod->flags;
dvander@67
    56
		}
dvander@67
    57
		else if (!(plugin->data) && !strcmp(nameptr, ".data"))
dvander@67
    58
		{
dvander@67
    59
			sp_file_data_t *dat = (sp_file_data_t *)(base + secptr->dataoffs);
dvander@67
    60
			plugin->data = base + secptr->dataoffs + dat->data;
dvander@67
    61
			plugin->data_size = dat->datasize;
dvander@67
    62
			plugin->memory = dat->memsize;
dvander@67
    63
		}
dvander@67
    64
		else if (!(plugin->info.publics) && !strcmp(nameptr, ".publics"))
dvander@67
    65
		{
dvander@67
    66
			plugin->info.publics_num = secptr->size / sizeof(sp_file_publics_t);
dvander@67
    67
			plugin->info.publics = (sp_file_publics_t *)(base + secptr->dataoffs);
dvander@67
    68
		}
dvander@67
    69
		else if (!(plugin->info.pubvars) && !strcmp(nameptr, ".pubvars"))
dvander@67
    70
		{
dvander@67
    71
			plugin->info.pubvars_num = secptr->size / sizeof(sp_file_pubvars_t);
dvander@67
    72
			plugin->info.pubvars = (sp_file_pubvars_t *)(base + secptr->dataoffs);
dvander@67
    73
		}
dvander@67
    74
		else if (!(plugin->info.natives) && !strcmp(nameptr, ".natives"))
dvander@67
    75
		{
dvander@67
    76
			plugin->info.natives_num = secptr->size / sizeof(sp_file_natives_t);
dvander@67
    77
			plugin->info.natives = (sp_file_natives_t *)(base + secptr->dataoffs);
dvander@67
    78
		}
dvander@67
    79
		else if (!(plugin->info.stringbase) && !strcmp(nameptr, ".names"))
dvander@67
    80
		{
dvander@67
    81
			plugin->info.stringbase = (const char *)(base + secptr->dataoffs);
dvander@67
    82
		}
dvander@67
    83
		else if (!(plugin->debug.files) && !strcmp(nameptr, ".dbg.files"))
dvander@67
    84
		{
dvander@67
    85
			plugin->debug.files = (sp_fdbg_file_t *)(base + secptr->dataoffs);
dvander@67
    86
		}
dvander@67
    87
		else if (!(plugin->debug.lines) && !strcmp(nameptr, ".dbg.lines"))
dvander@67
    88
		{
dvander@67
    89
			plugin->debug.lines = (sp_fdbg_line_t *)(base + secptr->dataoffs);
dvander@67
    90
		}
dvander@67
    91
		else if (!(plugin->debug.symbols) && !strcmp(nameptr, ".dbg.symbols"))
dvander@67
    92
		{
dvander@67
    93
			plugin->debug.symbols = (sp_fdbg_symbol_t *)(base + secptr->dataoffs);
dvander@67
    94
		}
dvander@67
    95
		else if (!(plugin->debug.lines_num) && !strcmp(nameptr, ".dbg.info"))
dvander@67
    96
		{
dvander@67
    97
			sp_fdbg_info_t *inf = (sp_fdbg_info_t *)(base + secptr->dataoffs);
dvander@67
    98
			plugin->debug.files_num = inf->num_files;
dvander@67
    99
			plugin->debug.lines_num = inf->num_lines;
dvander@67
   100
			plugin->debug.syms_num = inf->num_syms;
dvander@67
   101
		}
dvander@67
   102
		else if (!(plugin->debug.stringbase) && !strcmp(nameptr, ".dbg.strings"))
dvander@67
   103
		{
dvander@67
   104
			plugin->debug.stringbase = (const char *)(base + secptr->dataoffs);
dvander@67
   105
		}
dvander@67
   106
dvander@67
   107
		secptr++;
dvander@67
   108
		sectnum++;
dvander@67
   109
	}
dvander@67
   110
dvander@67
   111
	if (!(plugin->pcode) || !(plugin->data) || !(plugin->info.stringbase))
dvander@67
   112
	{
dvander@67
   113
		goto return_error;
dvander@67
   114
	}
dvander@67
   115
dvander@67
   116
	if ((plugin->flags & SP_FLAG_DEBUG) && (!(plugin->debug.files) || !(plugin->debug.lines) || !(plugin->debug.symbols)))
dvander@67
   117
	{
dvander@67
   118
		goto return_error;
dvander@67
   119
	}
dvander@67
   120
dvander@67
   121
	if (err)
dvander@67
   122
	{
dvander@67
   123
		*err = SP_ERR_NONE;
dvander@67
   124
	}
dvander@67
   125
dvander@67
   126
	return plugin;
dvander@67
   127
dvander@67
   128
return_error:
dvander@67
   129
	if (err)
dvander@67
   130
	{
dvander@67
   131
		*err = SP_ERR_FILE_FORMAT;
dvander@67
   132
	}
dvander@67
   133
dvander@67
   134
	return NULL;
dvander@67
   135
}
dvander@67
   136
dvander@67
   137
sp_plugin_t *SourcePawnEngine::LoadFromFilePointer(FILE *fp, int *err)
dvander@67
   138
{
dvander@67
   139
	sp_file_hdr_t hdr;
dvander@67
   140
	sp_plugin_t *plugin;
dvander@67
   141
	uint8_t *base;
dvander@67
   142
	int z_result;
dvander@67
   143
	int error;
dvander@67
   144
dvander@67
   145
	if (!fp)
dvander@67
   146
	{
dvander@67
   147
		error = SP_ERR_NOT_FOUND;
dvander@67
   148
		goto return_error;
dvander@67
   149
	}
dvander@67
   150
dvander@67
   151
	/* Rewind for safety */
dvander@67
   152
	rewind(fp);
dvander@67
   153
	fread(&hdr, sizeof(sp_file_hdr_t), 1, fp);
dvander@67
   154
dvander@67
   155
	if (hdr.magic != SPFILE_MAGIC)
dvander@67
   156
	{
dvander@67
   157
		error = SP_ERR_FILE_FORMAT;
dvander@67
   158
		goto return_error;
dvander@67
   159
	}
dvander@67
   160
dvander@67
   161
	switch (hdr.compression)
dvander@67
   162
	{
dvander@67
   163
	case SPFILE_COMPRESSION_GZ:
dvander@67
   164
		{
dvander@67
   165
			uint32_t uncompsize = hdr.imagesize - hdr.dataoffs;
dvander@67
   166
			uint32_t compsize = hdr.disksize - hdr.dataoffs;
dvander@67
   167
			uint32_t sectsize = hdr.dataoffs - sizeof(sp_file_hdr_t);
dvander@67
   168
			uLongf destlen = uncompsize;
dvander@67
   169
dvander@67
   170
			char *tempbuf = (char *)malloc(compsize);
dvander@67
   171
			void *uncompdata = malloc(uncompsize);
dvander@67
   172
			void *sectheader = malloc(sectsize);
dvander@67
   173
dvander@67
   174
			fread(sectheader, sectsize, 1, fp);
dvander@67
   175
			fread(tempbuf, compsize, 1, fp);
dvander@67
   176
dvander@67
   177
			z_result = uncompress((Bytef *)uncompdata, &destlen, (Bytef *)tempbuf, compsize);
dvander@67
   178
			free(tempbuf);
dvander@67
   179
			if (z_result != Z_OK)
dvander@67
   180
			{
dvander@67
   181
				free(sectheader);
dvander@67
   182
				free(uncompdata);
dvander@67
   183
				error = SP_ERR_DECOMPRESSOR;
dvander@67
   184
				goto return_error;
dvander@67
   185
			}
dvander@67
   186
dvander@67
   187
			base = (uint8_t *)malloc(hdr.imagesize);
dvander@67
   188
			memcpy(base, &hdr, sizeof(sp_file_hdr_t));
dvander@67
   189
			memcpy(base + sizeof(sp_file_hdr_t), sectheader, sectsize);
dvander@67
   190
			free(sectheader);
dvander@67
   191
			memcpy(base + hdr.dataoffs, uncompdata, uncompsize);
dvander@67
   192
			free(uncompdata);
dvander@67
   193
			break;
dvander@67
   194
		}
dvander@67
   195
	case SPFILE_COMPRESSION_NONE:
dvander@67
   196
		{
dvander@67
   197
			base = (uint8_t *)malloc(hdr.imagesize);
dvander@67
   198
			rewind(fp);
dvander@67
   199
			fread(base, hdr.imagesize, 1, fp);
dvander@67
   200
			break;
dvander@67
   201
		}
dvander@67
   202
	default:
dvander@67
   203
		{
dvander@67
   204
			error = SP_ERR_DECOMPRESSOR;
dvander@67
   205
			goto return_error;
dvander@67
   206
		}
dvander@67
   207
	}
dvander@67
   208
dvander@67
   209
	plugin = (sp_plugin_t *)malloc(sizeof(sp_plugin_t));
dvander@67
   210
	if (!_ReadPlugin(&hdr, base, plugin, err))
dvander@67
   211
	{
dvander@67
   212
		free(plugin);
dvander@67
   213
		free(base);
dvander@67
   214
		return NULL;
dvander@67
   215
	}
dvander@67
   216
dvander@67
   217
	plugin->allocflags = 0;
dvander@67
   218
dvander@67
   219
	return plugin;
dvander@67
   220
dvander@67
   221
return_error:
dvander@67
   222
	if (err)
dvander@67
   223
	{
dvander@67
   224
		*err = error;
dvander@67
   225
	}
dvander@67
   226
	return NULL;
dvander@67
   227
}
dvander@67
   228
dvander@67
   229
sp_plugin_t *SourcePawnEngine::LoadFromMemory(void *base, sp_plugin_t *plugin, int *err)
dvander@67
   230
{
dvander@67
   231
	sp_file_hdr_t hdr;
dvander@67
   232
	uint8_t noptr = 0;
dvander@67
   233
dvander@67
   234
	memcpy(&hdr, base, sizeof(sp_file_hdr_t));
dvander@67
   235
dvander@67
   236
	if (!plugin)
dvander@67
   237
	{
dvander@67
   238
		plugin = (sp_plugin_t *)malloc(sizeof(sp_plugin_t));
dvander@67
   239
		noptr = 1;
dvander@67
   240
	}
dvander@67
   241
dvander@67
   242
	if (!_ReadPlugin(&hdr, (uint8_t *)base, plugin, err))
dvander@67
   243
	{
dvander@67
   244
		if (noptr)
dvander@67
   245
		{
dvander@67
   246
			free(plugin);
dvander@67
   247
		}
dvander@67
   248
		return NULL;
dvander@67
   249
	}
dvander@67
   250
dvander@67
   251
	if (!noptr)
dvander@67
   252
	{
dvander@67
   253
		plugin->allocflags |= SP_FA_SELF_EXTERNAL;
dvander@67
   254
	}
dvander@67
   255
	plugin->allocflags |= SP_FA_BASE_EXTERNAL;
dvander@67
   256
dvander@67
   257
	return plugin;
dvander@67
   258
}
dvander@67
   259
dvander@67
   260
int SourcePawnEngine::FreeFromMemory(sp_plugin_t *plugin)
dvander@67
   261
{
dvander@67
   262
	if (!(plugin->allocflags & SP_FA_BASE_EXTERNAL))
dvander@67
   263
	{
dvander@67
   264
		free(plugin->base);
dvander@67
   265
		plugin->base = NULL;
dvander@67
   266
	}
dvander@67
   267
	if (!(plugin->allocflags & SP_FA_SELF_EXTERNAL))
dvander@67
   268
	{
dvander@67
   269
		free(plugin);
dvander@67
   270
	}
dvander@67
   271
dvander@67
   272
	return SP_ERR_NONE;
dvander@67
   273
}