346 lines
8 KiB
C
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;
|
|
}
|