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