|
|
|
#include "forth_internal.h"
|
|
|
|
|
|
|
|
static void show_word(struct fh_thread_s *fh, const struct fh_word_s *w)
|
|
|
|
{
|
|
|
|
if (!w) {
|
|
|
|
LOGE("NULL!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
FHPRINT("Dict entry at 0x%08x\n", word_addr(fh, w));
|
|
|
|
if (w->flags & WORDFLAG_WORD) {
|
|
|
|
if (w->handler == w_user_word) {
|
|
|
|
uint32_t execptr = w->param;
|
|
|
|
|
|
|
|
FHPRINT("Compiled word %s%s\n", w->name, (w->flags & WORDFLAG_IMMEDIATE) ? " IMMEDIATE" : "");
|
|
|
|
while (1) {
|
|
|
|
// make sure it's aligned
|
|
|
|
execptr = WORDALIGNED(execptr);
|
|
|
|
FHPRINT("0x%08x: ", execptr);
|
|
|
|
const struct fh_instruction_s *instr = fh_instr_at(fh, execptr);
|
|
|
|
if (!instr) {
|
|
|
|
LOGE("Word pointer out of bounds!");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
execptr += INSTR_SIZE;
|
|
|
|
|
|
|
|
uint32_t strl;
|
|
|
|
const struct fh_word_s *w2;
|
|
|
|
switch (instr->kind) {
|
|
|
|
case FH_INSTR_NUMBER:
|
|
|
|
FHPRINT("Number(%d / 0x%08x)\n", instr->data, instr->data);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FH_INSTR_WORD:
|
|
|
|
w2 = fh_word_at(fh, instr->data);
|
|
|
|
if (w2) {
|
|
|
|
FHPRINT("Call(word %s)\n", w2->name);
|
|
|
|
} else {
|
|
|
|
FHPRINT("Call(BAD ADDRESS!!! 0x%08x)\n", instr->data);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FH_INSTR_POSTPONED_WORD:
|
|
|
|
w2 = fh_word_at(fh, instr->data);
|
|
|
|
if (w2) {
|
|
|
|
if (w2->name[0]) {
|
|
|
|
FHPRINT("Postpone(word %s)\n", w2->name);
|
|
|
|
} else {
|
|
|
|
FHPRINT("Postpone(word 0x%08x)\n", instr->data);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
FHPRINT("Postpone(BAD ADDRESS!!! 0x%08x)\n", instr->data);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FH_INSTR_OF:
|
|
|
|
FHPRINT("OF(value %d / 0x%08x)\n", instr->data, instr->data);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FH_INSTR_ENDCASE:
|
|
|
|
FHPRINT("ENDCASE\n");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FH_INSTR_TO:
|
|
|
|
w2 = fh_word_at(fh, instr->data);
|
|
|
|
if (w2) {
|
|
|
|
if (w2->name[0]) {
|
|
|
|
FHPRINT("To(var %s)\n", w2->name);
|
|
|
|
} else {
|
|
|
|
FHPRINT("To(var 0x%08x)\n", instr->data);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
FHPRINT("To(BAD ADDRESS!!! 0x%08x)\n", instr->data);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FH_INSTR_JUMPZERO:
|
|
|
|
FHPRINT("JumpIfZero(dest 0x%08x)\n", instr->data);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FH_INSTR_JUMP:
|
|
|
|
FHPRINT("Jump(dest 0x%08x)\n", instr->data);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FH_INSTR_DO:
|
|
|
|
FHPRINT("DO\n");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FH_INSTR_DO_QUESTION:
|
|
|
|
FHPRINT("DO?(end 0x%08x)\n", instr->data);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FH_INSTR_LOOP:
|
|
|
|
FHPRINT("LOOP(start 0x%08x)\n", instr->data);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FH_INSTR_LOOP_PLUS:
|
|
|
|
FHPRINT("LOOP+(start 0x%08x)\n", instr->data);
|
|
|
|
break;
|
|
|
|
|
|
|
|
/* special case for strings stored in compile memory */
|
|
|
|
case FH_INSTR_ALLOCSTR:
|
|
|
|
case FH_INSTR_TYPESTR:
|
|
|
|
strl = instr->data;
|
|
|
|
if (instr->kind == FH_INSTR_ALLOCSTR) {
|
|
|
|
FHPRINT("AllocStr(\"%.*s\")\n", strl, fh_str_at(fh, execptr));
|
|
|
|
execptr += strl;
|
|
|
|
} else {
|
|
|
|
FHPRINT("PrintStr(\"%.*s\")\n", strl, fh_str_at(fh, execptr));
|
|
|
|
execptr += strl;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case FH_INSTR_ENDWORD:
|
|
|
|
if (instr->data == 1) {
|
|
|
|
FHPRINT("END (synthetic for DOES>)\n");
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
FHPRINT("END\n");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
default:
|
|
|
|
FHPRINT("Unknown(kind 0x%08x, data 0x%08x)\n", instr->kind, instr->data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
FHPRINT("Built-in word %s\n", w->name);
|
|
|
|
};
|
|
|
|
} else if (w->flags & WORDFLAG_VARIABLE) {
|
|
|
|
FHPRINT("Variable %s, value %d (0x%08x)\n", w->name, (int32_t) w->param, w->param);
|
|
|
|
} else if (w->flags & WORDFLAG_CONSTANT) {
|
|
|
|
FHPRINT("Constant %s, value %d (0x%08x)\n", w->name, (int32_t) w->param, w->param);
|
|
|
|
} else if (w->flags & WORDFLAG_CREATED) {
|
|
|
|
FHPRINT("CREATE'd entry %s, param %d (0x%08x)\n", w->name, (int32_t) w->param, w->param);
|
|
|
|
} else {
|
|
|
|
FHPRINT("Unknown entry %s, param %d (0x%08x)\n", w->name, (int32_t) w->param, w->param);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/** Decompile a word */
|
|
|
|
enum fh_error fh_see_word(
|
|
|
|
struct fh_thread_s *fh,
|
|
|
|
const char *name,
|
|
|
|
const size_t wordlen
|
|
|
|
)
|
|
|
|
{
|
|
|
|
enum fh_error rv;
|
|
|
|
uint32_t addr;
|
|
|
|
// TODO allow see with addr to inspect :NONAME defined words
|
|
|
|
TRY(fh_find_word(fh, name, wordlen, &addr));
|
|
|
|
show_word(fh, fh_word_at(fh, addr));
|
|
|
|
return FH_OK;
|
|
|
|
}
|