sourcepawn/decompiler/decompiler.cpp
author David Anderson <dvander@alliedmods.net>
Tue Sep 23 21:20:40 2008 -0700 (2008-09-23)
changeset 2320 88550c031d23
child 2325 7a24ee5557fb
permissions -rw-r--r--
Initial import/sketch of opcode analyzer (bug 3279).
Uses single static assignment to recover expression trees from straight-line byte code.
     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <string.h>
     4 #include <stdarg.h>
     5 #include "decompiler.h"
     6 #include "platform_util.h"
     7 
     8 sp_decomp_t *Sp_InitDecomp(const char *file, int *err)
     9 {
    10 	sp_decomp_t *dc;
    11 	sp_file_t *plugin;
    12 
    13 	if ((plugin = Sp_ReadPlugin(file, err)) == NULL)
    14 	{
    15 		return NULL;
    16 	}
    17 
    18 	dc = new sp_decomp_t;
    19 	memset(dc, 0, sizeof(sp_decomp_t));
    20 	dc->plugin = plugin;
    21 	dc->pcode_map = (cell_t *)malloc(dc->plugin->pcode_size);
    22 	memset(dc->pcode_map, 0, dc->plugin->pcode_size);
    23 
    24 #define OPDEF(num,enm,str,prms)	\
    25 	dc->opdef[num].name = str;		\
    26 	dc->opdef[num].params = prms;
    27 #include "opcodes.tbl"
    28 #undef OPDEF
    29 
    30 	return dc;
    31 }
    32 
    33 void Sp_FreeDecomp(sp_decomp_t *decomp)
    34 {
    35 	FunctionInfo *info, *info_temp;
    36 
    37 	info = decomp->funcs;
    38 	while (info != NULL)
    39 	{
    40 		info_temp = info->next;
    41 		delete info;
    42 		info = info_temp;
    43 	}
    44 
    45 	Sp_FreePlugin(decomp->plugin);
    46 	free(decomp->pcode_map);
    47 	delete decomp;
    48 }
    49 
    50 PrintBuffer::PrintBuffer() : printbuf(NULL), printbuf_alloc(0), printbuf_pos(0)
    51 {
    52 }
    53 
    54 PrintBuffer::~PrintBuffer()
    55 {
    56 	free(printbuf);
    57 }
    58 
    59 void PrintBuffer::Grow(size_t len)
    60 {
    61 	if (printbuf_pos + len > printbuf_alloc)
    62 	{
    63 		if (printbuf_alloc == 0)
    64 		{
    65 			printbuf_alloc = len * 8;
    66 		}
    67 		else
    68 		{
    69 			printbuf_alloc += len;
    70 			printbuf_alloc *= 2;
    71 		}
    72 
    73 		printbuf = (char *)realloc(printbuf, printbuf_alloc);
    74 	}
    75 }
    76 
    77 void PrintBuffer::Append(const char *fmt, ...)
    78 {
    79 	size_t len;
    80 	va_list ap;
    81 	char buffer[2048];
    82 
    83 	va_start(ap, fmt);
    84 	len = Sp_FormatArgs(buffer, sizeof(buffer), fmt, ap);
    85 	va_end(ap);
    86 
    87 	Grow(len);
    88 
    89 	printbuf = (char *)realloc(printbuf, printbuf_alloc);
    90 	strcpy(&printbuf[printbuf_pos], buffer);
    91 	printbuf_pos += len;
    92 }
    93 
    94 void PrintBuffer::Set(const char *fmt, ...)
    95 {
    96 	size_t len;
    97 	va_list ap;
    98 	char buffer[2048];
    99 
   100 	va_start(ap, fmt);
   101 	len = Sp_FormatArgs(buffer, sizeof(buffer), fmt, ap);
   102 	va_end(ap);
   103 
   104 	Reset();
   105 	Grow(len);
   106 
   107 	printbuf = (char *)realloc(printbuf, printbuf_alloc);
   108 	strcpy(&printbuf[printbuf_pos], buffer);
   109 	printbuf_pos += len;
   110 }
   111 
   112 void PrintBuffer::Prepend(const char *fmt, ...)
   113 {
   114 	size_t len;
   115 	va_list ap;
   116 	char buffer[2048];
   117 
   118 	va_start(ap, fmt);
   119 	len = Sp_FormatArgs(buffer, sizeof(buffer), fmt, ap);
   120 	va_end(ap);
   121 
   122 	Grow(len + 1);
   123 
   124 	/* Move old data forward.  Move one extra byte for the null terminator. */
   125 	memmove(&printbuf[len], printbuf, printbuf_pos + 1);
   126 	printbuf_pos += len;
   127 	/* Move the new data in. */
   128 	memcpy(printbuf, buffer, len);
   129 }
   130 
   131 void PrintBuffer::Reset()
   132 {
   133 	printbuf_pos = 0;
   134 }
   135 
   136 void PrintBuffer::Dump(FILE *fp)
   137 {
   138 	fprintf(fp, "%s", printbuf);
   139 }