sourcepawn/decompiler/decompiler.cpp
author David Anderson <danderson@mozilla.com>
Thu Aug 08 09:40:23 2013 -0700 (2013-08-08)
changeset 3976 bc77cfde7c5c
parent 2325 7a24ee5557fb
permissions -rw-r--r--
Add -Wno-narrowing to support building on GCC-4.7 (no bug, r=me).
dvander@2320
     1
#include <stdio.h>
dvander@2320
     2
#include <stdlib.h>
dvander@2320
     3
#include <string.h>
dvander@2320
     4
#include <stdarg.h>
dvander@2325
     5
#include <assert.h>
dvander@2320
     6
#include "decompiler.h"
dvander@2320
     7
#include "platform_util.h"
dvander@2320
     8
dvander@2320
     9
sp_decomp_t *Sp_InitDecomp(const char *file, int *err)
dvander@2320
    10
{
dvander@2320
    11
	sp_decomp_t *dc;
dvander@2320
    12
	sp_file_t *plugin;
dvander@2320
    13
dvander@2320
    14
	if ((plugin = Sp_ReadPlugin(file, err)) == NULL)
dvander@2320
    15
	{
dvander@2320
    16
		return NULL;
dvander@2320
    17
	}
dvander@2320
    18
dvander@2320
    19
	dc = new sp_decomp_t;
dvander@2320
    20
	memset(dc, 0, sizeof(sp_decomp_t));
dvander@2320
    21
	dc->plugin = plugin;
dvander@2320
    22
	dc->pcode_map = (cell_t *)malloc(dc->plugin->pcode_size);
dvander@2320
    23
	memset(dc->pcode_map, 0, dc->plugin->pcode_size);
dvander@2320
    24
dvander@2320
    25
#define OPDEF(num,enm,str,prms)	\
dvander@2320
    26
	dc->opdef[num].name = str;		\
dvander@2320
    27
	dc->opdef[num].params = prms;
dvander@2320
    28
#include "opcodes.tbl"
dvander@2320
    29
#undef OPDEF
dvander@2320
    30
dvander@2325
    31
	if (plugin->debug.ntv != NULL)
dvander@2325
    32
	{
dvander@2325
    33
		assert(plugin->debug.ntv->num_entries == plugin->num_natives);
dvander@2325
    34
		dc->natives = new FunctionInfo[plugin->num_natives];
dvander@2325
    35
		memset(dc->natives, 0, sizeof(FunctionInfo) * plugin->num_natives);
dvander@2325
    36
dvander@2325
    37
		/* Unfurl this mess. */
dvander@2325
    38
		uint8_t *cursor = (uint8_t *)plugin->debug.ntv;
dvander@2325
    39
dvander@2325
    40
		cursor += sizeof(sp_fdbg_ntvtab_t);
dvander@2325
    41
		for (uint32_t i = 0; i < plugin->num_natives; i++)
dvander@2325
    42
		{
dvander@2325
    43
			sp_fdbg_native_t *native = (sp_fdbg_native_t *)cursor;
dvander@2325
    44
dvander@2325
    45
			uint32_t idx = native->index;
dvander@2325
    46
dvander@2325
    47
			assert(dc->natives[idx].name[0] == '\0');
dvander@2325
    48
dvander@2325
    49
			Sp_Format(dc->natives[idx].name, 
dvander@2325
    50
				sizeof(dc->natives[idx].name),
dvander@2325
    51
				"%s",
dvander@2325
    52
				plugin->debug.stringbase + native->name);
dvander@2325
    53
			dc->natives[idx].tag = Sp_FindTag(plugin, native->tagid);
dvander@2325
    54
			dc->natives[idx].num_known_args = native->nargs;
dvander@2325
    55
			
dvander@2325
    56
			cursor += sizeof(sp_fdbg_native_t);
dvander@2325
    57
dvander@2325
    58
			for (uint32_t j = 0; j < dc->natives[idx].num_known_args; j++)
dvander@2325
    59
			{
dvander@2325
    60
				sp_fdbg_ntvarg_t *arg = (sp_fdbg_ntvarg_t *)cursor;
dvander@2325
    61
				dc->natives[idx].known_args[j].name = 
dvander@2325
    62
					plugin->debug.stringbase + arg->name;
dvander@2325
    63
				dc->natives[idx].known_args[j].tag = 
dvander@2325
    64
					Sp_FindTag(plugin, arg->tagid);
dvander@2325
    65
				dc->natives[idx].known_args[j].dimcount = arg->dimcount;
dvander@2325
    66
dvander@2325
    67
				cursor += sizeof(sp_fdbg_ntvarg_t);
dvander@2325
    68
				if (arg->dimcount != 0)
dvander@2325
    69
				{
dvander@2325
    70
					dc->natives[idx].known_args[j].dims = (sp_fdbg_arraydim_t *)cursor;
dvander@2325
    71
					cursor += sizeof(sp_fdbg_arraydim_t) * arg->dimcount;
dvander@2325
    72
				}
dvander@2325
    73
			}
dvander@2325
    74
		}
dvander@2325
    75
	}
dvander@2325
    76
dvander@2320
    77
	return dc;
dvander@2320
    78
}
dvander@2320
    79
dvander@2320
    80
void Sp_FreeDecomp(sp_decomp_t *decomp)
dvander@2320
    81
{
dvander@2320
    82
	FunctionInfo *info, *info_temp;
dvander@2320
    83
dvander@2320
    84
	info = decomp->funcs;
dvander@2320
    85
	while (info != NULL)
dvander@2320
    86
	{
dvander@2320
    87
		info_temp = info->next;
dvander@2320
    88
		delete info;
dvander@2320
    89
		info = info_temp;
dvander@2320
    90
	}
dvander@2320
    91
dvander@2320
    92
	Sp_FreePlugin(decomp->plugin);
dvander@2320
    93
	free(decomp->pcode_map);
dvander@2325
    94
	delete [] decomp->natives;
dvander@2320
    95
	delete decomp;
dvander@2320
    96
}
dvander@2320
    97
dvander@2320
    98
PrintBuffer::PrintBuffer() : printbuf(NULL), printbuf_alloc(0), printbuf_pos(0)
dvander@2320
    99
{
dvander@2320
   100
}
dvander@2320
   101
dvander@2320
   102
PrintBuffer::~PrintBuffer()
dvander@2320
   103
{
dvander@2320
   104
	free(printbuf);
dvander@2320
   105
}
dvander@2320
   106
dvander@2320
   107
void PrintBuffer::Grow(size_t len)
dvander@2320
   108
{
dvander@2320
   109
	if (printbuf_pos + len > printbuf_alloc)
dvander@2320
   110
	{
dvander@2320
   111
		if (printbuf_alloc == 0)
dvander@2320
   112
		{
dvander@2320
   113
			printbuf_alloc = len * 8;
dvander@2320
   114
		}
dvander@2320
   115
		else
dvander@2320
   116
		{
dvander@2320
   117
			printbuf_alloc += len;
dvander@2320
   118
			printbuf_alloc *= 2;
dvander@2320
   119
		}
dvander@2320
   120
dvander@2320
   121
		printbuf = (char *)realloc(printbuf, printbuf_alloc);
dvander@2320
   122
	}
dvander@2320
   123
}
dvander@2320
   124
dvander@2320
   125
void PrintBuffer::Append(const char *fmt, ...)
dvander@2320
   126
{
dvander@2320
   127
	size_t len;
dvander@2320
   128
	va_list ap;
dvander@2320
   129
	char buffer[2048];
dvander@2320
   130
dvander@2320
   131
	va_start(ap, fmt);
dvander@2320
   132
	len = Sp_FormatArgs(buffer, sizeof(buffer), fmt, ap);
dvander@2320
   133
	va_end(ap);
dvander@2320
   134
dvander@2325
   135
	Grow(len + 1);
dvander@2320
   136
dvander@2320
   137
	strcpy(&printbuf[printbuf_pos], buffer);
dvander@2320
   138
	printbuf_pos += len;
dvander@2320
   139
}
dvander@2320
   140
dvander@2320
   141
void PrintBuffer::Set(const char *fmt, ...)
dvander@2320
   142
{
dvander@2320
   143
	size_t len;
dvander@2320
   144
	va_list ap;
dvander@2320
   145
	char buffer[2048];
dvander@2320
   146
dvander@2320
   147
	va_start(ap, fmt);
dvander@2320
   148
	len = Sp_FormatArgs(buffer, sizeof(buffer), fmt, ap);
dvander@2320
   149
	va_end(ap);
dvander@2320
   150
dvander@2320
   151
	Reset();
dvander@2325
   152
	Grow(len + 1);
dvander@2320
   153
dvander@2320
   154
	printbuf = (char *)realloc(printbuf, printbuf_alloc);
dvander@2320
   155
	strcpy(&printbuf[printbuf_pos], buffer);
dvander@2320
   156
	printbuf_pos += len;
dvander@2320
   157
}
dvander@2320
   158
dvander@2320
   159
void PrintBuffer::Prepend(const char *fmt, ...)
dvander@2320
   160
{
dvander@2320
   161
	size_t len;
dvander@2320
   162
	va_list ap;
dvander@2320
   163
	char buffer[2048];
dvander@2320
   164
dvander@2320
   165
	va_start(ap, fmt);
dvander@2320
   166
	len = Sp_FormatArgs(buffer, sizeof(buffer), fmt, ap);
dvander@2320
   167
	va_end(ap);
dvander@2320
   168
dvander@2320
   169
	Grow(len + 1);
dvander@2320
   170
dvander@2320
   171
	/* Move old data forward.  Move one extra byte for the null terminator. */
dvander@2320
   172
	memmove(&printbuf[len], printbuf, printbuf_pos + 1);
dvander@2320
   173
	printbuf_pos += len;
dvander@2320
   174
	/* Move the new data in. */
dvander@2320
   175
	memcpy(printbuf, buffer, len);
dvander@2320
   176
}
dvander@2320
   177
dvander@2320
   178
void PrintBuffer::Reset()
dvander@2320
   179
{
dvander@2320
   180
	printbuf_pos = 0;
dvander@2320
   181
}
dvander@2320
   182
dvander@2320
   183
void PrintBuffer::Dump(FILE *fp)
dvander@2320
   184
{
dvander@2320
   185
	fprintf(fp, "%s", printbuf);
dvander@2320
   186
}