radare2/libr/vm/op.c
pancake 8f9dbbd0d1 * Remove some use of alloca()
* Fix lock when using 'r2 -d'
* Invalid program name results in error, not warning
2010-10-12 13:22:19 +02:00

103 lines
2.3 KiB
C

/* radare - LGPL - Copyright 2008-2010 pancake<nopcode.org> */
#include "r_vm.h"
R_API int r_vm_op_add(struct r_vm_t *vm, const char *op, const char *str) {
RVmOp *o = R_NEW (RVmOp);
if (o == NULL)
return -1;
strncpy(o->opcode, op, sizeof(o->opcode));
strncpy(o->code, str, sizeof(o->code));
list_add_tail(&(o->list), &vm->ops);
return 0;
}
R_API int r_vm_op_eval(struct r_vm_t *vm, const char *str) {
struct list_head *pos;
char *p, *s, *arg0;
int j, k, len = strlen(str)+256;
int nargs = 0;
p = alloca(len);
s = alloca(len);
memcpy (p, str, len);
memcpy (s, str, len);
r_str_subchr (s, ',', 0);
r_str_subchr (s, '\t', 0);
r_str_subchr (s, '#', 0);
nargs = r_str_word_set0(s);
arg0 = r_str_word_get0(s, 0);
list_for_each(pos, &vm->ops) {
struct r_vm_op_t *o = list_entry(pos, struct r_vm_op_t, list);
if (!strcmp (arg0, o->opcode)) {
str = o->code;
p = alloca (strlen (o->code)+128);
strcpy (p, str);
for (j=k=0;str[j]!='\0';j++,k++) {
if (str[j]=='$') {
j++;
if (str[j]=='\0') {
eprintf("invalid string\n");
return 0;
}
#if TODO
if (str[j]=='$') {
/* opcode size */
if (str[j+1]=='$') {
struct aop_t aop;
char w[32];
j++;
arch_aop(config.seek, config.block,&aop);
sprintf(w, "%d", aop.length);
if (w[0]) {
strcpy(p+k, w);
k += strlen(w)-1;
}
} else {
char w[32];
sprintf(w, "0x%08"PFMT64x"", config.seek);
if (w[0]) {
strcpy(p+k, w);
k += strlen(w)-1;
}
}
}
#endif
if (str[j]>='0' && str[j]<='9') {
const char *w = r_str_word_get0(s, str[j]-'0');
if (w != NULL) {
strcpy(p+k, w);
k += strlen(w)-1;
}
}
} else p[k] = str[j];
}
p[k]='\0';
}
}
return r_vm_eval (vm, p);
}
/* TODO : Allow to remove and so on */
R_API int r_vm_op_cmd(RVm *vm, const char *op) {
char *cmd, *ptr;
int len = strlen (op)+1;
if (*op==' ')
op = op + 1;
cmd = alloca(len);
memcpy (cmd, op, len);
ptr = strchr (cmd, ' ');
if (ptr) {
// XXX: merge those two functions in one
ptr[0]='\0';
if (!memcmp (op, "avo", 3)) {
r_vm_op_add (vm, cmd, ptr+1);
if (vm->log)
eprintf("vm: opcode '%s' added\n", cmd);
} else r_vm_cmd_reg (vm, op);
} else r_vm_cmd_op_help ();
return 0;
}