#include "forth_internal.h" static void show_word(struct fh_thread_s *fh, const struct fh_word_s *w) { if (!w) { LOGE("NULL!"); return; } 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)\n", 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_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: 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; TRY(fh_find_word(fh, name, wordlen, &addr)); show_word(fh, fh_word_at(fh, addr)); return FH_OK; }