#include #include #include #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; }