rizin/libr/asm/arch/whitespace/wsdis.c
2015-01-28 12:04:21 +01:00

346 lines
8 KiB
C

#include <r_types.h>
#include <r_asm.h>
#include <string.h>
#ifndef WS_API
#define WS_API
#endif
enum {
WS_OP_UNK = 0,
WS_OP_NOP,
WS_OP_PREF,
WS_OP_STACK,
WS_OP_ARITH,
WS_OP_HEAP,
WS_OP_FLOW,
WS_OP_IO
};
static int get_ws_pref_optype(const ut8 *buf, int len)
{
if(len) {
switch(buf[0]) {
case ' ':
return WS_OP_STACK;
case '\t':
return WS_OP_PREF;
case 10:
return WS_OP_FLOW;
default:
return WS_OP_NOP;
}
}
return WS_OP_UNK;
}
static int get_ws_suf_optype(const ut8 *buf, int len)
{
if(len) {
switch(buf[0]) {
case ' ':
return WS_OP_ARITH;
case '\t':
return WS_OP_HEAP;
case 10:
return WS_OP_IO;
default:
return WS_OP_NOP;
}
}
return WS_OP_UNK;
}
WS_API int get_ws_optype(const ut8 *buf, int len)
{
const ut8 *ptr;
if(get_ws_pref_optype(buf, len) == WS_OP_PREF) {
ptr = buf+1;
while(get_ws_suf_optype(ptr, len - ( ptr - buf )) == WS_OP_NOP)
ptr++;
return get_ws_suf_optype(ptr, len - ( ptr - buf));
}
return get_ws_pref_optype(buf, len);
}
WS_API const ut8 *get_ws_next_token(const ut8 *buf, int len)
{
const ut8 *ret;
ret = buf;
while(len - (ret - buf)) {
switch(*ret) {
case ' ':
case '\t':
case 10:
return ret;
}
ret++;
}
return NULL;
}
static st32 get_ws_val(const ut8 *buf, int len)
{
ut8 sig;
const ut8 *tok;
int i, ret;
ret = 0;
tok = get_ws_next_token(buf, len);
sig = (*tok == '\t');
len = len - (tok - buf) -1;
for(i=0; i<30; i++) { //XXX : conceptually wrong
tok++;
tok = get_ws_next_token(tok, len);
if(!tok || *tok == 10) {
if(sig)
return ret * (-1);
return ret;
}
ret = (ret << 1);
ret = ret + (*tok == '\t');
len = len - (tok - buf) -1;
}
if(sig)
return ret * (-1);
return ret;
}
WS_API int test_ws_token_exist(const ut8 *buf, ut8 token, int len)
{
const ut8 *ptr;
ptr = get_ws_next_token(buf, len);
while(ptr && *ptr!=token && (len > 0)) {
len = len - (ptr - buf);
ptr = get_ws_next_token(ptr + 1, len - 1);
}
if(ptr)
return (ptr-buf);
return -1;
}
WS_API int wsdis(RAsmOp *op, const ut8 *buf, int len)
{
const ut8 *ptr;
ptr = buf;
switch(get_ws_optype(buf, len)) {
case WS_OP_UNK:
return op->size = 0;
case WS_OP_NOP:
sprintf(op->buf_asm, "nop");
return op->size = 1;
case WS_OP_STACK:
ptr++;
if(!get_ws_next_token(ptr, len -1))
return op->size = 0;
switch(*get_ws_next_token(ptr, len - 1)) {
case ' ':
if(-1 == test_ws_token_exist(get_ws_next_token(ptr, len - 1), 10, len - 1))
return op->size = 0;
sprintf(op->buf_asm, "push");
sprintf(&op->buf_asm[4], " %d", get_ws_val(ptr + 1, len - 1));
return op->size = test_ws_token_exist(ptr - 1, 10, len) + 1;
case 10:
ptr = get_ws_next_token(ptr, len -1) + 1;
ptr = get_ws_next_token(ptr, len - (ptr - buf));
if(!ptr)
return op->size = 0;
switch(*ptr) {
case ' ':
sprintf(op->buf_asm, "dup");
break;
case '\t':
sprintf(op->buf_asm, "swap");
break;
case 10:
sprintf(op->buf_asm, "pop");
break;
}
return op->size = ptr - buf + 1;
case '\t':
ptr = get_ws_next_token(ptr, len -1) + 1;
ptr = get_ws_next_token(ptr, len - (ptr - buf));
if(!ptr)
return op->size = 0;
switch(*ptr) {
case ' ':
sprintf(op->buf_asm, "copy");
break;
case 10:
sprintf(op->buf_asm, "slide");
break;
case '\t':
sprintf(op->buf_asm, "illegal_stack_t");
return op->size = ptr - buf + 1;
}
ptr ++;
if(-1 == test_ws_token_exist(ptr, 10, len - (ptr - buf) -1)) {
op->buf_asm[0] = '\0'; //XXX
return op->size = 0;
}
if(strlen(op->buf_asm) < 6)
sprintf(&op->buf_asm[strlen(op->buf_asm)], " %d", get_ws_val(ptr, len - (ptr - buf) - 1));
return op->size = test_ws_token_exist(ptr, 10, len - (ptr - buf) -1) + ptr - buf + 1; //+1?
}
case WS_OP_HEAP:
ptr = get_ws_next_token(ptr + 1, len - 1) + 1;
ptr = get_ws_next_token(ptr, len - (ptr - buf));
if(!ptr)
return op->size = 0;
switch(*ptr) {
case ' ':
sprintf(op->buf_asm, "store");
break;
case '\t':
sprintf(op->buf_asm, "load");
break;
case 10:
sprintf(op->buf_asm, "illegal_heap");
break;
}
return op->size = ptr - buf + 1;
case WS_OP_IO:
ptr = get_ws_next_token(ptr + 1, len - 1) + 1;
ptr = get_ws_next_token(ptr, len - (ptr - buf));
if(!ptr)
return op->size = 0;
switch(*ptr) {
case ' ':
ptr++;
ptr = get_ws_next_token(ptr, len - (ptr - buf));
if(!ptr)
return op->size = 0;
switch(*ptr) {
case ' ':
sprintf(op->buf_asm, "putc");
return op->size = ptr - buf + 1;
case '\t':
sprintf(op->buf_asm, "puti");
return op->size = ptr - buf + 1;
}
break;
case '\t':
ptr++;
ptr = get_ws_next_token(ptr, len - (ptr - buf));
if(!ptr)
return op->size = 0;
switch(*ptr) {
case ' ':
sprintf(op->buf_asm, "getc");
return op->size = ptr - buf + 1;
case '\t':
sprintf(op->buf_asm, "geti");
return op->size = ptr - buf + 1;
}
}
sprintf(op->buf_asm, "illegal_io");
return op->size = ptr - buf + 1;
case WS_OP_ARITH:
ptr = get_ws_next_token(ptr + 1, len - 1) + 1;
ptr = get_ws_next_token(ptr, len - (ptr - buf));
if(!ptr)
return op->size = 0;
switch(*ptr) {
case ' ':
ptr++;
ptr = get_ws_next_token(ptr, len - (ptr - buf));
if(!ptr)
return op->size = 0;
switch(*ptr) {
case ' ':
sprintf(op->buf_asm, "add");
break;
case '\t':
sprintf(op->buf_asm, "sub");
break;
case 10:
sprintf(op->buf_asm, "mul");
break;
}
return op->size = ptr - buf + 1;
case '\t':
ptr++;
ptr = get_ws_next_token(ptr, len - (ptr -buf));
if(!ptr)
return op->size = 0;
switch(*ptr) {
case ' ':
sprintf(op->buf_asm, "div");
break;
case '\t':
sprintf(op->buf_asm, "mod");
break;
case 10:
sprintf(op->buf_asm, "illegal_ar_t");
}
break;
case 10:
sprintf(op->buf_asm, "illegal_ar");
}
return op->size = ptr - buf + 1;
case WS_OP_FLOW:
ptr = get_ws_next_token(ptr + 1, len -1);
if(!ptr) //evil
return op->size = 0;
switch(*ptr) {
case 10:
ptr++;
ptr = get_ws_next_token(ptr, len - (ptr - buf));
if(!ptr)
return op->size = 0;
if(*ptr == 10)
sprintf(op->buf_asm, "exit");
else
sprintf(op->buf_asm, "illegal_fl_lf");
return op->size = ptr - buf + 1;
case '\t':
ptr++;
ptr = get_ws_next_token(ptr, len - (ptr - buf));
if(!ptr)
return op->size = 0;
switch(*ptr) {
case 10:
sprintf(op->buf_asm, "ret");
return op->size = ptr - buf + 1;
case '\t':
sprintf(op->buf_asm, "jn");
break;
case ' ':
sprintf(op->buf_asm, "jz");
break;
}
ptr++;
if(-1 == test_ws_token_exist(ptr, 10, len - (ptr - buf))) {
op->buf_asm[0] = '\0';
return op->size = 0;
}
if(strlen(op->buf_asm) == 2)
sprintf(&op->buf_asm[2], " %d", get_ws_val(ptr, len - (ptr- buf) -1));
return op->size = ptr - buf + test_ws_token_exist(ptr, 10, len - (ptr - buf)) + 1;
case ' ':
ptr++;
ptr = get_ws_next_token(ptr, len - (ptr - buf));
if(!ptr)
return op->size = 0;
switch(*ptr) {
case 10:
sprintf(op->buf_asm, "jmp");
break;
case '\t':
sprintf(op->buf_asm, "call");
break;
case ' ':
sprintf(op->buf_asm, "mark");
break;
}
ptr++;
if(-1 == test_ws_token_exist(ptr, 10, len - (ptr - buf))) {
op->buf_asm[0] = '\0';
return op->size = 0;
}
sprintf(&op->buf_asm[strlen(op->buf_asm)], " %d", get_ws_val(ptr, len - (ptr - buf) -1));
return op->size = ptr - buf + test_ws_token_exist(ptr, 10, len - (ptr - buf)) + 1;
}
}
sprintf(op->buf_asm,"wtf");
return op->size = 0;
}