reformat code, some cleaning

master
Ondřej Hruška 3 years ago
parent 8248637157
commit cab55d835b
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 2
      include/fh_builtins.h
  2. 8
      include/fh_mem.h
  3. 9
      include/fh_runtime.h
  4. 16
      include/fh_stack.h
  5. 122
      src/fh_builtins_arith.c
  6. 13
      src/fh_builtins_control.c
  7. 65
      src/fh_builtins_mem.c
  8. 171
      src/fh_builtins_meta.c
  9. 40
      src/fh_builtins_stack.c
  10. 8
      src/fh_builtins_system.c
  11. 160
      src/fh_builtins_text.c
  12. 29
      src/fh_mem.c
  13. 72
      src/fh_parse.c
  14. 68
      src/fh_runtime.c
  15. 8
      src/fh_see.c
  16. 4
      src/fh_stack.c

@ -36,7 +36,9 @@ extern const struct name_and_handler fh_builtins_text[];
extern const struct name_and_handler fh_builtins_system[]; extern const struct name_and_handler fh_builtins_system[];
enum fh_error wp_const(struct fh_thread_s *fh, const struct fh_word_s *w); enum fh_error wp_const(struct fh_thread_s *fh, const struct fh_word_s *w);
enum fh_error wp_mul(struct fh_thread_s *fh, const struct fh_word_s *w); enum fh_error wp_mul(struct fh_thread_s *fh, const struct fh_word_s *w);
enum fh_error wp_add(struct fh_thread_s *fh, const struct fh_word_s *w); enum fh_error wp_add(struct fh_thread_s *fh, const struct fh_word_s *w);
#endif //FORTH_FH_BUILTINS_H #endif //FORTH_FH_BUILTINS_H

@ -26,15 +26,21 @@ enum fh_error fh_heap_reserve(
size_t len, size_t len,
uint32_t *addr uint32_t *addr
); );
void fh_heap_write(struct fh_thread_s *fh, uint32_t addr, const void *src, uint32_t len); void fh_heap_write(struct fh_thread_s *fh, uint32_t addr, const void *src, uint32_t len);
enum fh_error fh_heap_put(struct fh_thread_s *fh, const void *src, uint32_t len); enum fh_error fh_heap_put(struct fh_thread_s *fh, const void *src, uint32_t len);
void fh_heap_copy(struct fh_thread_s *fh, uint32_t addr, uint32_t srcaddr, uint32_t len); void fh_heap_copy(struct fh_thread_s *fh, uint32_t addr, uint32_t srcaddr, uint32_t len);
void fh_heap_copyptr(struct fh_thread_s *fh, uint32_t addr, char * source, uint32_t len);
void fh_heap_copyptr(struct fh_thread_s *fh, uint32_t addr, char *source, uint32_t len);
enum fh_error fh_put_instr(struct fh_thread_s *fh, enum fh_instruction_kind kind, uint32_t data); enum fh_error fh_put_instr(struct fh_thread_s *fh, enum fh_instruction_kind kind, uint32_t data);
char *fh_str_at(struct fh_thread_s *fh, uint32_t addr); char *fh_str_at(struct fh_thread_s *fh, uint32_t addr);
struct fh_instruction_s *fh_instr_at(struct fh_thread_s *fh, uint32_t addr); struct fh_instruction_s *fh_instr_at(struct fh_thread_s *fh, uint32_t addr);
struct fh_word_s *fh_word_at(struct fh_thread_s *fh, uint32_t addr); struct fh_word_s *fh_word_at(struct fh_thread_s *fh, uint32_t addr);
#endif //FORTH_FH_MEM_H #endif //FORTH_FH_MEM_H

@ -49,7 +49,7 @@ enum fh_instruction_kind {
/* Jump if zero */ /* Jump if zero */
FH_INSTR_JUMPZERO, FH_INSTR_JUMPZERO,
/* Jump if the two elements on stack do not equal, consuming the top one. /* Jump if the two elements on stack do not equal, consuming the top one.
* Otherwise consume both and continue. */ * Otherwise consume both and continue. */
FH_INSTR_OF, FH_INSTR_OF,
@ -215,7 +215,7 @@ struct fh_thread_s {
/** Nesting level of [if] */ /** Nesting level of [if] */
uint32_t parse_if_level; uint32_t parse_if_level;
bool executing_compiled; bool executing_compiled;
}; };
@ -267,8 +267,9 @@ enum fh_error fh_init(struct fh_thread_s *fh);
enum fh_error fh_process_line(struct fh_thread_s *fh, const char *linebuf, size_t len); enum fh_error fh_process_line(struct fh_thread_s *fh, const char *linebuf, size_t len);
static inline uint32_t word_addr(struct fh_thread_s *fh, const struct fh_word_s *w) { static inline uint32_t word_addr(struct fh_thread_s *fh, const struct fh_word_s *w)
return (uint32_t) ((void*)w - (void*)&fh->heap[0]); {
return (uint32_t) ((void *) w - (void *) &fh->heap[0]);
} }
#endif //FORTH_FH_RUNTIME_H #endif //FORTH_FH_RUNTIME_H

@ -11,14 +11,18 @@ enum fh_error ds_roll(struct fh_thread_s *fh, int n);
/** Peek n-th element of data stack, 0=topmost */ /** Peek n-th element of data stack, 0=topmost */
enum fh_error ds_peek_n(struct fh_thread_s *fh, uint32_t *out, int n); enum fh_error ds_peek_n(struct fh_thread_s *fh, uint32_t *out, int n);
/** Peek n-th element of return stack, 0=topmost */ /** Peek n-th element of return stack, 0=topmost */
enum fh_error rs_peek_n(struct fh_thread_s *fh, uint32_t *out, int n); enum fh_error rs_peek_n(struct fh_thread_s *fh, uint32_t *out, int n);
/** Peek n-th element of control stack, 0=topmost */ /** Peek n-th element of control stack, 0=topmost */
static inline enum fh_error cs_peek_n(struct fh_thread_s *fh, uint32_t *out, int n) { static inline enum fh_error cs_peek_n(struct fh_thread_s *fh, uint32_t *out, int n)
{
return ds_peek_n(fh, out, n); return ds_peek_n(fh, out, n);
} }
enum fh_error ds_push_dw(struct fh_thread_s *fh, uint64_t in); enum fh_error ds_push_dw(struct fh_thread_s *fh, uint64_t in);
enum fh_error ds_pop_dw(struct fh_thread_s *fh, uint64_t *out); enum fh_error ds_pop_dw(struct fh_thread_s *fh, uint64_t *out);
enum fh_error rs_poke_n(struct fh_thread_s *fh, uint32_t value, int n); enum fh_error rs_poke_n(struct fh_thread_s *fh, uint32_t value, int n);
@ -42,14 +46,20 @@ static inline enum fh_error cs_peek(struct fh_thread_s *fh, uint32_t *out)
} }
enum fh_error ds_pop(struct fh_thread_s *fh, uint32_t *out); enum fh_error ds_pop(struct fh_thread_s *fh, uint32_t *out);
enum fh_error rs_pop(struct fh_thread_s *fh, uint32_t *out); enum fh_error rs_pop(struct fh_thread_s *fh, uint32_t *out);
static inline enum fh_error cs_pop(struct fh_thread_s *fh, uint32_t *out) {
static inline enum fh_error cs_pop(struct fh_thread_s *fh, uint32_t *out)
{
return ds_pop(fh, out); return ds_pop(fh, out);
} }
enum fh_error ds_push(struct fh_thread_s *fh, uint32_t in); enum fh_error ds_push(struct fh_thread_s *fh, uint32_t in);
enum fh_error rs_push(struct fh_thread_s *fh, uint32_t in); enum fh_error rs_push(struct fh_thread_s *fh, uint32_t in);
static inline enum fh_error cs_push(struct fh_thread_s *fh, uint32_t in) {
static inline enum fh_error cs_push(struct fh_thread_s *fh, uint32_t in)
{
return ds_push(fh, in); return ds_push(fh, in);
} }

@ -193,7 +193,7 @@ static enum fh_error w_within(struct fh_thread_s *fh, const struct fh_word_s *w)
TRY(ds_pop(fh, &high)); TRY(ds_pop(fh, &high));
TRY(ds_pop(fh, &low)); TRY(ds_pop(fh, &low));
TRY(ds_pop(fh, &test)); TRY(ds_pop(fh, &test));
// This should work, according to the spec: // This should work, according to the spec:
// : WITHIN ( test low high -- flag ) OVER - >R - R> U< ; // : WITHIN ( test low high -- flag ) OVER - >R - R> U< ;
@ -204,13 +204,13 @@ static enum fh_error w_within(struct fh_thread_s *fh, const struct fh_word_s *w)
// (t-l) | R:(h-l) | R> // (t-l) | R:(h-l) | R>
// (t-l) (h-l) | U< // (t-l) (h-l) | U<
// =within // =within
const int32_t ti = (int32_t)test; const int32_t ti = (int32_t) test;
const int32_t li = (int32_t)low; const int32_t li = (int32_t) low;
const int32_t hi = (int32_t)high; const int32_t hi = (int32_t) high;
const bool within = (uint32_t)(ti-li) < (uint32_t)(hi-li); const bool within = (uint32_t) (ti - li) < (uint32_t) (hi - li);
TRY(ds_push(fh, TOBOOL(within))); TRY(ds_push(fh, TOBOOL(within)));
return FH_OK; return FH_OK;
} }
@ -277,15 +277,6 @@ enum fh_error wp_mul(struct fh_thread_s *fh, const struct fh_word_s *w)
return FH_OK; return FH_OK;
} }
static enum fh_error wp_div(struct fh_thread_s *fh, const struct fh_word_s *w)
{
enum fh_error rv;
uint32_t a = 0;
TRY(ds_pop(fh, &a));
TRY(ds_push(fh, (int32_t) a / (int32_t) w->param));
return FH_OK;
}
static enum fh_error w_2div(struct fh_thread_s *fh, const struct fh_word_s *w) static enum fh_error w_2div(struct fh_thread_s *fh, const struct fh_word_s *w)
{ {
(void) w; (void) w;
@ -309,7 +300,7 @@ static enum fh_error w_star_slash(struct fh_thread_s *fh, const struct fh_word_s
return FH_ERR_ARITH; return FH_ERR_ARITH;
} }
int64_t v = ((int64_t) (int32_t)a * (int64_t) (int32_t)b) / (int64_t) (int32_t)c; int64_t v = ((int64_t) (int32_t) a * (int64_t) (int32_t) b) / (int64_t) (int32_t) c;
TRY(ds_push(fh, (uint32_t) v)); TRY(ds_push(fh, (uint32_t) v));
return FH_OK; return FH_OK;
@ -328,12 +319,12 @@ static enum fh_error w_star_slash_mod(struct fh_thread_s *fh, const struct fh_wo
return FH_ERR_ARITH; return FH_ERR_ARITH;
} }
int64_t product = ((int64_t) (int32_t)a * (int64_t) (int32_t)b); const int64_t product = ((int64_t) (int32_t) a * (int64_t) (int32_t) b);
int64_t v = product / (int64_t) (int32_t)c; const int64_t v = product / (int64_t) (int32_t) c;
int64_t m = product % (int64_t) (int32_t)c; const int64_t m = product % (int64_t) (int32_t) c;
TRY(ds_push(fh, (uint32_t) (int32_t)m)); TRY(ds_push(fh, (uint32_t) (int32_t) m));
TRY(ds_push(fh, (uint32_t) (int32_t)v)); TRY(ds_push(fh, (uint32_t) (int32_t) v));
return FH_OK; return FH_OK;
} }
@ -349,7 +340,7 @@ static enum fh_error w_slash(struct fh_thread_s *fh, const struct fh_word_s *w)
return FH_ERR_ARITH; return FH_ERR_ARITH;
} }
TRY(ds_push(fh, (int32_t)a / (int32_t)b)); TRY(ds_push(fh, (int32_t) a / (int32_t) b));
return FH_OK; return FH_OK;
} }
@ -360,7 +351,7 @@ static enum fh_error w_abs(struct fh_thread_s *fh, const struct fh_word_s *w)
uint32_t a = 0; uint32_t a = 0;
TRY(ds_pop(fh, &a)); TRY(ds_pop(fh, &a));
int32_t sa = (int32_t) a; // TODO is this right? int32_t sa = (int32_t) a;
if (sa < 0) { sa = -sa; } if (sa < 0) { sa = -sa; }
@ -400,8 +391,8 @@ static enum fh_error w_slash_mod(struct fh_thread_s *fh, const struct fh_word_s
return FH_ERR_ARITH; return FH_ERR_ARITH;
} }
int32_t rem = (int32_t)a % (int32_t)b; const int32_t rem = (int32_t) a % (int32_t) b;
int32_t div = (int32_t)a / (int32_t)b; const int32_t div = (int32_t) a / (int32_t) b;
TRY(ds_push(fh, rem)); TRY(ds_push(fh, rem));
TRY(ds_push(fh, div)); TRY(ds_push(fh, div));
@ -420,7 +411,7 @@ static enum fh_error w_mod(struct fh_thread_s *fh, const struct fh_word_s *w)
return FH_ERR_ARITH; return FH_ERR_ARITH;
} }
int32_t rem = (int32_t)a % (int32_t)b; const int32_t rem = (int32_t) a % (int32_t) b;
TRY(ds_push(fh, rem)); TRY(ds_push(fh, rem));
return FH_OK; return FH_OK;
@ -433,8 +424,8 @@ static enum fh_error w_s_to_d(struct fh_thread_s *fh, const struct fh_word_s *w)
uint32_t a = 0; uint32_t a = 0;
TRY(ds_pop(fh, &a)); TRY(ds_pop(fh, &a));
int32_t as = (int32_t) a; // because of sign extend const int32_t as = (int32_t) a; // because of sign extend
int64_t a64 = as; const int64_t a64 = as;
TRY(ds_push_dw(fh, (uint64_t) a64)); TRY(ds_push_dw(fh, (uint64_t) a64));
return FH_OK; return FH_OK;
@ -449,7 +440,7 @@ static enum fh_error w_m_star(struct fh_thread_s *fh, const struct fh_word_s *w)
TRY(ds_pop(fh, &b)); TRY(ds_pop(fh, &b));
// make signed and then sign extend // make signed and then sign extend
int64_t res = (int64_t) (int32_t) a * (int64_t) (int32_t) b; const int64_t res = (int64_t) (int32_t) a * (int64_t) (int32_t) b;
TRY(ds_push_dw(fh, (uint64_t) res)); TRY(ds_push_dw(fh, (uint64_t) res));
return FH_OK; return FH_OK;
@ -464,7 +455,7 @@ static enum fh_error w_um_star(struct fh_thread_s *fh, const struct fh_word_s *w
TRY(ds_pop(fh, &b)); TRY(ds_pop(fh, &b));
// make signed and then sign extend // make signed and then sign extend
uint64_t res = (uint64_t) a * (uint64_t) b; const uint64_t res = (uint64_t) a * (uint64_t) b;
TRY(ds_push_dw(fh, res)); TRY(ds_push_dw(fh, res));
return FH_OK; return FH_OK;
@ -473,16 +464,15 @@ static enum fh_error w_um_star(struct fh_thread_s *fh, const struct fh_word_s *w
// Copied from https://stackoverflow.com/a/51457071/2180189 // Copied from https://stackoverflow.com/a/51457071/2180189
void floor_div64(int64_t *q, int64_t *r, int64_t a, int64_t b) void floor_div64(int64_t *q, int64_t *r, int64_t a, int64_t b)
{ {
int64_t q0 = a / b; const int64_t q0 = a / b;
int64_t r0 = a % b; const int64_t r0 = a % b;
if (b > 0){ if (b > 0) {
*q = r0 >= 0 ? q0 : q0 - 1; *q = r0 >= 0 ? q0 : q0 - 1;
*r = r0 >= 0 ? r0 : r0 + b; *r = r0 >= 0 ? r0 : r0 + b;
} } else {
else { *q = r0 <= 0 ? q0 : q0 - 1;
*q = r0 <= 0 ? q0 : q0 - 1; *r = r0 <= 0 ? r0 : r0 + b;
*r = r0 <= 0 ? r0 : r0 + b; }
}
} }
static enum fh_error w_fm_mod(struct fh_thread_s *fh, const struct fh_word_s *w) static enum fh_error w_fm_mod(struct fh_thread_s *fh, const struct fh_word_s *w)
@ -491,24 +481,24 @@ static enum fh_error w_fm_mod(struct fh_thread_s *fh, const struct fh_word_s *w)
enum fh_error rv; enum fh_error rv;
int32_t div; int32_t div;
int64_t num; int64_t num;
TRY(ds_pop(fh, (uint32_t*)&div)); TRY(ds_pop(fh, (uint32_t *) &div));
TRY(ds_pop_dw(fh, (uint64_t*)&num)); TRY(ds_pop_dw(fh, (uint64_t *) &num));
int64_t res, rem; int64_t res, rem;
floor_div64(&res, &rem, num, div); floor_div64(&res, &rem, num, div);
if ((int64_t)(int32_t)rem != rem) { if ((int64_t) (int32_t) rem != rem) {
LOGE("Remainder too large"); LOGE("Remainder too large");
return FH_ERR_ARITH; return FH_ERR_ARITH;
} }
if ((int64_t)(int32_t)res != res) { if ((int64_t) (int32_t) res != res) {
LOGE("Division result too large"); LOGE("Division result too large");
return FH_ERR_ARITH; return FH_ERR_ARITH;
} }
TRY(ds_push(fh, (int32_t)rem)); TRY(ds_push(fh, (int32_t) rem));
TRY(ds_push(fh, (int32_t)res)); TRY(ds_push(fh, (int32_t) res));
return FH_OK; return FH_OK;
} }
@ -521,20 +511,20 @@ static enum fh_error w_um_mod(struct fh_thread_s *fh, const struct fh_word_s *w)
TRY(ds_pop(fh, &div)); TRY(ds_pop(fh, &div));
TRY(ds_pop_dw(fh, &num)); TRY(ds_pop_dw(fh, &num));
uint64_t res = num / (uint64_t)div; const uint64_t res = num / (uint64_t) div;
uint64_t rem = num % (uint64_t)div; const uint64_t rem = num % (uint64_t) div;
if ((uint64_t)(uint32_t)rem != rem) { if ((uint64_t) (uint32_t) rem != rem) {
LOGE("Remainder too large"); LOGE("Remainder too large");
return FH_ERR_ARITH; return FH_ERR_ARITH;
} }
if ((uint64_t)(uint32_t)res != res) { if ((uint64_t) (uint32_t) res != res) {
LOGE("Division result too large"); LOGE("Division result too large");
return FH_ERR_ARITH; return FH_ERR_ARITH;
} }
TRY(ds_push(fh, (uint32_t)rem)); TRY(ds_push(fh, (uint32_t) rem));
TRY(ds_push(fh, (uint32_t)res)); TRY(ds_push(fh, (uint32_t) res));
return FH_OK; return FH_OK;
} }
@ -544,23 +534,23 @@ static enum fh_error w_sm_rem(struct fh_thread_s *fh, const struct fh_word_s *w)
enum fh_error rv; enum fh_error rv;
int32_t div; int32_t div;
int64_t num; int64_t num;
TRY(ds_pop(fh, (uint32_t*)&div)); TRY(ds_pop(fh, (uint32_t *) &div));
TRY(ds_pop_dw(fh, (uint64_t*)&num)); TRY(ds_pop_dw(fh, (uint64_t *) &num));
int64_t res = num / (int64_t)div; const int64_t res = num / (int64_t) div;
int64_t rem = num % (int64_t)div; const int64_t rem = num % (int64_t) div;
if ((int64_t)(int32_t)rem != rem) { if ((int64_t) (int32_t) rem != rem) {
LOGE("Remainder too large"); LOGE("Remainder too large");
return FH_ERR_ARITH; return FH_ERR_ARITH;
} }
if ((int64_t)(int32_t)res != res) { if ((int64_t) (int32_t) res != res) {
LOGE("Division result too large"); LOGE("Division result too large");
return FH_ERR_ARITH; return FH_ERR_ARITH;
} }
TRY(ds_push(fh, (int32_t)rem)); TRY(ds_push(fh, (int32_t) rem));
TRY(ds_push(fh, (int32_t)res)); TRY(ds_push(fh, (int32_t) res));
return FH_OK; return FH_OK;
} }
@ -608,9 +598,9 @@ const struct name_and_handler fh_builtins_arith[] = {
{"s>d", w_s_to_d, 0, 0}, {"s>d", w_s_to_d, 0, 0},
{"m*", w_m_star, 0, 0}, {"m*", w_m_star, 0, 0},
{"um*", w_um_star, 0, 0}, {"um*", w_um_star, 0, 0},
{"fm/mod", w_fm_mod, 0, 0}, {"fm/mod", w_fm_mod, 0, 0},
{"sm/rem", w_sm_rem, 0, 0}, {"sm/rem", w_sm_rem, 0, 0},
{"um/mod", w_um_mod, 0, 0}, {"um/mod", w_um_mod, 0, 0},
{"within", w_within, 0, 0}, {"within", w_within, 0, 0},
{ /* end marker */ } { /* end marker */ }
}; };

@ -225,7 +225,6 @@ static enum fh_error wp_ij(struct fh_thread_s *fh, const struct fh_word_s *w)
} }
static enum fh_error w_case(struct fh_thread_s *fh, const struct fh_word_s *w) static enum fh_error w_case(struct fh_thread_s *fh, const struct fh_word_s *w)
{ {
(void) w; (void) w;
@ -252,7 +251,7 @@ static enum fh_error w_endof(struct fh_thread_s *fh, const struct fh_word_s *w)
ENSURE_STATE(FH_STATE_COMPILE); ENSURE_STATE(FH_STATE_COMPILE);
uint32_t ofaddr; uint32_t ofaddr;
TRY(cs_pop(fh, &ofaddr)); TRY(cs_pop(fh, &ofaddr));
struct fh_instruction_s *of_instr = fh_instr_at(fh, ofaddr); struct fh_instruction_s *of_instr = fh_instr_at(fh, ofaddr);
if (!of_instr || of_instr->data != MAGICADDR_UNRESOLVED) { if (!of_instr || of_instr->data != MAGICADDR_UNRESOLVED) {
LOGE("CASE-OF control stack corruption"); LOGE("CASE-OF control stack corruption");
@ -272,12 +271,12 @@ static enum fh_error w_endcase(struct fh_thread_s *fh, const struct fh_word_s *w
ENSURE_STATE(FH_STATE_COMPILE); ENSURE_STATE(FH_STATE_COMPILE);
uint32_t caseaddr; uint32_t caseaddr;
TRY(cs_pop(fh, &caseaddr)); TRY(cs_pop(fh, &caseaddr));
// Now walk the instructions and resolve every MAGICADDR_ENDCASE_UNRESOLVED // Now walk the instructions and resolve every MAGICADDR_ENDCASE_UNRESOLVED
uint32_t caseendaddr = fh->here; uint32_t caseendaddr = fh->here;
struct fh_instruction_s *ii; struct fh_instruction_s *ii;
// Resolve ENDOF. TODO copied from LOOP impl, unify? // Resolve ENDOF. TODO copied from LOOP impl, unify?
while (caseaddr < caseendaddr) { while (caseaddr < caseendaddr) {
ii = fh_instr_at(fh, caseaddr); ii = fh_instr_at(fh, caseaddr);
@ -298,9 +297,9 @@ static enum fh_error w_endcase(struct fh_thread_s *fh, const struct fh_word_s *w
caseaddr += INSTR_SIZE; caseaddr += INSTR_SIZE;
} }
} }
TRY(fh_put_instr(fh, FH_INSTR_ENDCASE, 0)); TRY(fh_put_instr(fh, FH_INSTR_ENDCASE, 0));
return FH_OK; return FH_OK;
} }

@ -108,7 +108,7 @@ static enum fh_error w_buffer_colon(struct fh_thread_s *fh, const struct fh_word
(void) w; (void) w;
enum fh_error rv; enum fh_error rv;
ENSURE_STATE(FH_STATE_INTERPRET); ENSURE_STATE(FH_STATE_INTERPRET);
uint32_t count = 0; uint32_t count = 0;
TRY(ds_pop(fh, &count)); TRY(ds_pop(fh, &count));
TRY(fh_heap_reserve(fh, count, NULL)); TRY(fh_heap_reserve(fh, count, NULL));
@ -117,13 +117,13 @@ static enum fh_error w_buffer_colon(struct fh_thread_s *fh, const struct fh_word
size_t namelen = 0; size_t namelen = 0;
fh_input_consume_spaces(fh); fh_input_consume_spaces(fh);
TRY(fh_input_read_word(fh, &wordname, &namelen)); TRY(fh_input_read_word(fh, &wordname, &namelen));
LOG("Buffer name: %.*s", namelen, wordname); LOG("Buffer name: %.*s", (int) namelen, wordname);
uint32_t ptr; uint32_t ptr;
TRY(fh_heap_reserve(fh, DICTWORD_SIZE + count, &ptr)); TRY(fh_heap_reserve(fh, DICTWORD_SIZE + count, &ptr));
struct fh_word_s *new_word = fh_word_at(fh, ptr); struct fh_word_s *new_word = fh_word_at(fh, ptr);
if (!new_word) return FH_ERR_INTERNAL; if (!new_word) { return FH_ERR_INTERNAL; }
new_word->previous = fh->dict_last; new_word->previous = fh->dict_last;
new_word->param = ptr + DICTWORD_SIZE; new_word->param = ptr + DICTWORD_SIZE;
new_word->handler = rt_read_buffer_addr; new_word->handler = rt_read_buffer_addr;
@ -144,19 +144,19 @@ static enum fh_error w_move(struct fh_thread_s *fh, const struct fh_word_s *w)
TRY(ds_pop(fh, &count)); TRY(ds_pop(fh, &count));
TRY(ds_pop(fh, &dst)); TRY(ds_pop(fh, &dst));
TRY(ds_pop(fh, &src)); TRY(ds_pop(fh, &src));
if (src+count>=HEAP_SIZE) { if (src + count >= HEAP_SIZE) {
LOGE("MOVE src out of bounds"); LOGE("MOVE src out of bounds");
return FH_ERR_ILLEGAL_FETCH; return FH_ERR_ILLEGAL_FETCH;
} }
if (dst+count>=HEAP_SIZE) { if (dst + count >= HEAP_SIZE) {
LOGE("MOVE dst out of bounds"); LOGE("MOVE dst out of bounds");
return FH_ERR_ILLEGAL_STORE; return FH_ERR_ILLEGAL_STORE;
} }
fh_heap_copy(fh, dst, src, count); fh_heap_copy(fh, dst, src, count);
return FH_OK; return FH_OK;
} }
@ -219,7 +219,6 @@ static enum fh_error w_c_fetch(struct fh_thread_s *fh, const struct fh_word_s *w
static enum fh_error w_align(struct fh_thread_s *fh, const struct fh_word_s *w) static enum fh_error w_align(struct fh_thread_s *fh, const struct fh_word_s *w)
{ {
(void) w; (void) w;
enum fh_error rv;
fh->here = WORDALIGNED(fh->here); fh->here = WORDALIGNED(fh->here);
return FH_OK; return FH_OK;
} }
@ -253,9 +252,9 @@ static enum fh_error w_erase(struct fh_thread_s *fh, const struct fh_word_s *w)
uint32_t addr, len; uint32_t addr, len;
TRY(ds_pop(fh, &len)); TRY(ds_pop(fh, &len));
TRY(ds_pop(fh, &addr)); TRY(ds_pop(fh, &addr));
if (len > 0) { if (len > 0) {
if (addr+len < HEAP_SIZE) { if (addr + len < HEAP_SIZE) {
LOG("Erase at 0x%08x, len %d", addr, len); LOG("Erase at 0x%08x, len %d", addr, len);
memset(&fh->heap[addr], 0, len); memset(&fh->heap[addr], 0, len);
} }
@ -264,28 +263,28 @@ static enum fh_error w_erase(struct fh_thread_s *fh, const struct fh_word_s *w)
} }
const struct name_and_handler fh_builtins_mem[] = { const struct name_and_handler fh_builtins_mem[] = {
{"chars", wp_mul, 0, 1}, {"chars", wp_mul, 0, 1},
{"char+", wp_add, 0, 1}, {"char+", wp_add, 0, 1},
{"cells", wp_mul, 0, CELL}, {"cells", wp_mul, 0, CELL},
{"cell+", wp_add, 0, CELL}, {"cell+", wp_add, 0, CELL},
{"@", w_fetch, 0, 0}, {"@", w_fetch, 0, 0},
{"!", w_store, 0, 0}, {"!", w_store, 0, 0},
{"+!", w_plus_store, 0, 0}, {"+!", w_plus_store, 0, 0},
{"2!", w_two_store, 0, 0}, {"2!", w_two_store, 0, 0},
{"2@", w_two_fetch, 0, 0}, {"2@", w_two_fetch, 0, 0},
{"aligned", w_aligned, 0, 0}, {"aligned", w_aligned, 0, 0},
{"allot", w_allot, 0, 0}, {"allot", w_allot, 0, 0},
{"buffer:", w_buffer_colon, 0, 0}, {"buffer:", w_buffer_colon, 0, 0},
{"erase", w_erase, 0, 0}, {"erase", w_erase, 0, 0},
{"align", w_align, 0, 0}, {"align", w_align, 0, 0},
{",", w_comma, 0, 0}, {",", w_comma, 0, 0},
{"c,", w_c_comma, 0, 0}, {"c,", w_c_comma, 0, 0},
{"c@", w_c_fetch, 0, 0}, {"c@", w_c_fetch, 0, 0},
{"c!", w_c_store, 0, 0}, {"c!", w_c_store, 0, 0},
{"here", w_here, 0, 0}, {"here", w_here, 0, 0},
{"state", wp_const, 0, MAGICADDR_STATE}, {"state", wp_const, 0, MAGICADDR_STATE},
{"pad", w_pad, 0, 0}, {"pad", w_pad, 0, 0},
{"move", w_move, 0, 0}, {"move", w_move, 0, 0},
{ /* end marker */ } { /* end marker */ }
}; };

@ -10,7 +10,7 @@ static enum fh_error w_colon(struct fh_thread_s *fh, const struct fh_word_s *w)
size_t namelen = 0; size_t namelen = 0;
fh_input_consume_spaces(fh); fh_input_consume_spaces(fh);
TRY(fh_input_read_word(fh, &wordname, &namelen)); TRY(fh_input_read_word(fh, &wordname, &namelen));
LOG("Name: %.*s", namelen, wordname); LOG("Name: %.*s", (int) namelen, wordname);
fh_setstate(fh, FH_STATE_COMPILE, 0); fh_setstate(fh, FH_STATE_COMPILE, 0);
@ -18,7 +18,7 @@ static enum fh_error w_colon(struct fh_thread_s *fh, const struct fh_word_s *w)
TRY(fh_heap_reserve(fh, DICTWORD_SIZE, &ptr)); TRY(fh_heap_reserve(fh, DICTWORD_SIZE, &ptr));
struct fh_word_s *new_word = fh_word_at(fh, ptr); struct fh_word_s *new_word = fh_word_at(fh, ptr);
if (!new_word) return FH_ERR_INTERNAL; if (!new_word) { return FH_ERR_INTERNAL; }
new_word->previous = fh->dict_last; new_word->previous = fh->dict_last;
new_word->param = fh->here; new_word->param = fh->here;
new_word->handler = w_user_word; new_word->handler = w_user_word;
@ -48,13 +48,13 @@ static enum fh_error w_marker(struct fh_thread_s *fh, const struct fh_word_s *w)
size_t namelen = 0; size_t namelen = 0;
fh_input_consume_spaces(fh); fh_input_consume_spaces(fh);
TRY(fh_input_read_word(fh, &wordname, &namelen)); TRY(fh_input_read_word(fh, &wordname, &namelen));
LOG("Marker name: %.*s", namelen, wordname); LOG("Marker name: %.*s", (int) namelen, wordname);
uint32_t ptr; uint32_t ptr;
TRY(fh_heap_reserve(fh, DICTWORD_SIZE, &ptr)); TRY(fh_heap_reserve(fh, DICTWORD_SIZE, &ptr));
struct fh_word_s *new_word = fh_word_at(fh, ptr); struct fh_word_s *new_word = fh_word_at(fh, ptr);
if (!new_word) return FH_ERR_INTERNAL; if (!new_word) { return FH_ERR_INTERNAL; }
new_word->previous = fh->dict_last; new_word->previous = fh->dict_last;
new_word->param = fh->dict_last; new_word->param = fh->dict_last;
new_word->handler = rt_marker; new_word->handler = rt_marker;
@ -81,14 +81,14 @@ static enum fh_error w_colon_noname(struct fh_thread_s *fh, const struct fh_word
TRY(fh_heap_reserve(fh, DICTWORD_SIZE, &ptr)); TRY(fh_heap_reserve(fh, DICTWORD_SIZE, &ptr));
struct fh_word_s *new_word = fh_word_at(fh, ptr); struct fh_word_s *new_word = fh_word_at(fh, ptr);
if (!new_word) return FH_ERR_INTERNAL; if (!new_word) { return FH_ERR_INTERNAL; }
//new_word->previous = MAGICADDR_DICTFIRST; //new_word->previous = MAGICADDR_DICTFIRST;
new_word->previous = fh->dict_last; new_word->previous = fh->dict_last;
new_word->param = fh->here; new_word->param = fh->here;
new_word->handler = w_user_word; new_word->handler = w_user_word;
new_word->name[0] = 0; // no name, really new_word->name[0] = 0; // no name, really
new_word->flags = WORDFLAG_WORD | WORDFLAG_HIDDEN; new_word->flags = WORDFLAG_WORD | WORDFLAG_HIDDEN;
TRY(ds_push(fh, ptr)); // TODO maybe should do this at semicolon? TRY(ds_push(fh, ptr)); // TODO maybe should do this at semicolon?
fh->dict_last = ptr; fh->dict_last = ptr;
@ -100,31 +100,31 @@ static enum fh_error w_does(struct fh_thread_s *fh, const struct fh_word_s *w)
{ {
(void) w; (void) w;
enum fh_error rv; enum fh_error rv;
if (fh->executing_compiled) { if (fh->executing_compiled) {
struct fh_word_s *last_word = fh_word_at(fh, fh->dict_last); struct fh_word_s *last_word = fh_word_at(fh, fh->dict_last);
if (!last_word) return FH_ERR_INTERNAL; if (!last_word) { return FH_ERR_INTERNAL; }
last_word->param = fh->execptr + INSTR_SIZE; last_word->param = fh->execptr + INSTR_SIZE;
last_word->handler = w_user_word; last_word->handler = w_user_word;
last_word->flags = WORDFLAG_WORD | WORDFLAG_CREATED; last_word->flags = WORDFLAG_WORD | WORDFLAG_CREATED;
return FH_OK; return FH_OK;
} }
if (fh->state == FH_STATE_COMPILE) { if (fh->state == FH_STATE_COMPILE) {
TRY(fh_put_instr(fh, FH_INSTR_WORD, (void*)w - (void*)&fh->heap[0])); // call the DOES word TRY(fh_put_instr(fh, FH_INSTR_WORD, (void *) w - (void *) &fh->heap[0])); // call the DOES word
TRY(fh_put_instr(fh, FH_INSTR_ENDWORD, 1)); // synthetic exit so we dont also run the "postponed" DOES> content TRY(fh_put_instr(fh, FH_INSTR_ENDWORD, 1)); // synthetic exit so we dont also run the "postponed" DOES> content
return FH_OK; return FH_OK;
} }
fh_setstate(fh, FH_STATE_COMPILE, 0); fh_setstate(fh, FH_STATE_COMPILE, 0);
struct fh_word_s *last_word = fh_word_at(fh, fh->dict_last); struct fh_word_s *last_word = fh_word_at(fh, fh->dict_last);
if (!last_word) return FH_ERR_INTERNAL; if (!last_word) { return FH_ERR_INTERNAL; }
last_word->handler = w_user_word; last_word->handler = w_user_word;
last_word->param = fh->here; last_word->param = fh->here;
last_word->flags = WORDFLAG_WORD | WORDFLAG_CREATED; last_word->flags = WORDFLAG_WORD | WORDFLAG_CREATED;
return FH_OK; return FH_OK;
} }
@ -138,13 +138,13 @@ static enum fh_error w_forget(struct fh_thread_s *fh, const struct fh_word_s *w)
size_t namelen = 0; size_t namelen = 0;
fh_input_consume_spaces(fh); fh_input_consume_spaces(fh);
TRY(fh_input_read_word(fh, &wordname, &namelen)); TRY(fh_input_read_word(fh, &wordname, &namelen));
LOG("Name to forget: %.*s", namelen, wordname); LOG("Name to forget: %.*s", (int) namelen, wordname);
uint32_t addr; uint32_t addr;
TRY(fh_find_word(fh, wordname, namelen, &addr)); TRY(fh_find_word(fh, wordname, namelen, &addr));
struct fh_word_s *removedword = fh_word_at(fh, addr); struct fh_word_s *removedword = fh_word_at(fh, addr);
if (!removedword) return FH_ERR_INTERNAL; if (!removedword) { return FH_ERR_INTERNAL; }
fh->dict_last = removedword->previous; fh->dict_last = removedword->previous;
return FH_OK; return FH_OK;
} }
@ -188,7 +188,7 @@ static enum fh_error wp_variable(struct fh_thread_s *fh, const struct fh_word_s
bool is_const = w->param == 2; bool is_const = w->param == 2;
if (is_const && fh->state == FH_STATE_COMPILE) { if (is_const && fh->state == FH_STATE_COMPILE) {
uint32_t wordaddr = (void *)w - (void *)&fh->heap[0]; // this is ugly uint32_t wordaddr = (void *) w - (void *) &fh->heap[0]; // this is ugly
TRY(fh_put_instr(fh, FH_INSTR_WORD, wordaddr)); TRY(fh_put_instr(fh, FH_INSTR_WORD, wordaddr));
return FH_OK; return FH_OK;
} }
@ -210,7 +210,7 @@ static enum fh_error wp_variable(struct fh_thread_s *fh, const struct fh_word_s
TRY(fh_heap_reserve(fh, DICTWORD_SIZE, &ptr)); TRY(fh_heap_reserve(fh, DICTWORD_SIZE, &ptr));
struct fh_word_s *new_word = fh_word_at(fh, ptr); struct fh_word_s *new_word = fh_word_at(fh, ptr);
if (!new_word) return FH_ERR_INTERNAL; if (!new_word) { return FH_ERR_INTERNAL; }
new_word->previous = fh->dict_last; new_word->previous = fh->dict_last;
new_word->param = value; new_word->param = value;
new_word->handler = (is_value || is_const) ? rt_read_value : rt_read_varaddr; new_word->handler = (is_value || is_const) ? rt_read_value : rt_read_varaddr;
@ -247,7 +247,7 @@ static enum fh_error w_to(struct fh_thread_s *fh, const struct fh_word_s *w)
TRY(fh_find_word(fh, wordname, namelen, &waddr)); TRY(fh_find_word(fh, wordname, namelen, &waddr));
struct fh_word_s *ww = fh_word_at(fh, waddr); struct fh_word_s *ww = fh_word_at(fh, waddr);
if (!ww) return FH_ERR_INTERNAL; if (!ww) { return FH_ERR_INTERNAL; }
if (ww->flags & WORDFLAG_WORD) { if (ww->flags & WORDFLAG_WORD) {
LOGE("Cannot assign to dictionary word param field!"); LOGE("Cannot assign to dictionary word param field!");
@ -328,7 +328,7 @@ static enum fh_error w_semicolon(struct fh_thread_s *fh, const struct fh_word_s
// XXX if there was another definition previously and it was used in some other compiled function, // XXX if there was another definition previously and it was used in some other compiled function,
// that old implementation will still be called. // that old implementation will still be called.
// unhide the entry, if hidden (colon does this to make the word unresolvable before it's finished) // unhide the entry, if hidden (colon does this to make the word unresolvable before it's finished)
struct fh_word_s *ww = fh_word_at(fh, fh->dict_last); struct fh_word_s *ww = fh_word_at(fh, fh->dict_last);
if (ww && (ww->flags & WORDFLAG_WORD) && ww->name[0] != 0) { if (ww && (ww->flags & WORDFLAG_WORD) && ww->name[0] != 0) {
@ -342,7 +342,7 @@ static enum fh_error w_compile_comma(struct fh_thread_s *fh, const struct fh_wor
{ {
(void) w; (void) w;
enum fh_error rv; enum fh_error rv;
uint32_t xt; uint32_t xt;
TRY(ds_pop(fh, &xt)); TRY(ds_pop(fh, &xt));
TRY(fh_put_instr(fh, FH_INSTR_WORD, xt)); TRY(fh_put_instr(fh, FH_INSTR_WORD, xt));
@ -352,15 +352,13 @@ static enum fh_error w_compile_comma(struct fh_thread_s *fh, const struct fh_wor
static enum fh_error w_immediate(struct fh_thread_s *fh, const struct fh_word_s *w) static enum fh_error w_immediate(struct fh_thread_s *fh, const struct fh_word_s *w)
{ {
(void) w; (void) w;
enum fh_error rv;
if (fh->dict_last == 0) { if (fh->dict_last == 0) {
LOGE("Dict is empty, cannot modify previous word!"); LOGE("Dict is empty, cannot modify previous word!");
return FH_ERR_INVALID_STATE; return FH_ERR_INVALID_STATE;
} }
struct fh_word_s *word = fh_word_at(fh, fh->dict_last); struct fh_word_s *word = fh_word_at(fh, fh->dict_last);
if (!word) return FH_ERR_INTERNAL; if (!word) { return FH_ERR_INTERNAL; }
word->flags |= WORDFLAG_IMMEDIATE; word->flags |= WORDFLAG_IMMEDIATE;
return FH_OK; return FH_OK;
@ -429,10 +427,10 @@ static enum fh_error w_to_body(struct fh_thread_s *fh, const struct fh_word_s *w
{ {
(void) w; (void) w;
enum fh_error rv; enum fh_error rv;
uint32_t xt; uint32_t xt;
TRY(ds_pop(fh, &xt)); // xt is now a dict entry (hopefully) TRY(ds_pop(fh, &xt)); // xt is now a dict entry (hopefully)
TRY(ds_push(fh, xt + DICTWORD_SIZE)); // XXX should it still point here if DOES> was used? TRY(ds_push(fh, xt + DICTWORD_SIZE));
return FH_OK; return FH_OK;
} }
@ -466,8 +464,8 @@ static enum fh_error w_word(struct fh_thread_s *fh, const struct fh_word_s *w)
fh_store_char(fh, WORDBUF_ADDR, (char) len); fh_store_char(fh, WORDBUF_ADDR, (char) len);
fh_heap_copyptr(fh, WORDBUF_ADDR + 1, out, len); fh_heap_copyptr(fh, WORDBUF_ADDR + 1, out, len);
LOG("Word found: \"%.*s\"", len, out); LOG("Word found: \"%.*s\"", (int) len, out);
TRY(ds_push(fh, WORDBUF_ADDR)); TRY(ds_push(fh, WORDBUF_ADDR));
return FH_OK; return FH_OK;
@ -503,7 +501,7 @@ static enum fh_error w_create(struct fh_thread_s *fh, const struct fh_word_s *w)
TRY(fh_heap_reserve(fh, DICTWORD_SIZE, &ptr)); TRY(fh_heap_reserve(fh, DICTWORD_SIZE, &ptr));
struct fh_word_s *new_word = fh_word_at(fh, ptr); struct fh_word_s *new_word = fh_word_at(fh, ptr);
if (!new_word) return FH_ERR_INTERNAL; if (!new_word) { return FH_ERR_INTERNAL; }
new_word->previous = fh->dict_last; new_word->previous = fh->dict_last;
new_word->param = fh->here; new_word->param = fh->here;
new_word->handler = rt_read_value; new_word->handler = rt_read_value;
@ -537,7 +535,7 @@ static enum fh_error w_find(struct fh_thread_s *fh, const struct fh_word_s *w)
} }
struct fh_word_s *word = fh_word_at(fh, addr); struct fh_word_s *word = fh_word_at(fh, addr);
if (!word) return FH_ERR_INTERNAL; if (!word) { return FH_ERR_INTERNAL; }
TRY(ds_push(fh, addr)); TRY(ds_push(fh, addr));
TRY(ds_push(fh, (word->flags & WORDFLAG_IMMEDIATE) ? 1 : -1)); TRY(ds_push(fh, (word->flags & WORDFLAG_IMMEDIATE) ? 1 : -1));
@ -617,56 +615,41 @@ static enum fh_error w_env_query(struct fh_thread_s *fh, const struct fh_word_s
if (EQ(str, "/COUNTED-STRING", len)) { if (EQ(str, "/COUNTED-STRING", len)) {
TRY(ds_push(fh, 255)); TRY(ds_push(fh, 255));
TRY(ds_push(fh, 1)); TRY(ds_push(fh, 1));
} } else if (EQ(str, "/HOLD", len)) {
else if (EQ(str, "/HOLD", len)) {
TRY(ds_push(fh, WORDBUF_SIZE)); TRY(ds_push(fh, WORDBUF_SIZE));
TRY(ds_push(fh, 1)); TRY(ds_push(fh, 1));
} } else if (EQ(str, "/PAD", len)) {
else if (EQ(str, "/PAD", len)) {
TRY(ds_push(fh, MIN_PAD_SIZE)); TRY(ds_push(fh, MIN_PAD_SIZE));
TRY(ds_push(fh, 1)); TRY(ds_push(fh, 1));
} } else if (EQ(str, "ADDRESS-UNIT-BITS", len)) {
else if (EQ(str, "ADDRESS-UNIT-BITS", len)) {
TRY(ds_push(fh, 8)); TRY(ds_push(fh, 8));
TRY(ds_push(fh, 1)); TRY(ds_push(fh, 1));
} } else if (EQ(str, "FLOORED", len)) {
else if (EQ(str, "FLOORED", len)) { TRY(ds_push(fh, TOBOOL(1)));
TRY(ds_push(fh, TOBOOL(1))); // FIXME is it?
TRY(ds_push(fh, 1)); TRY(ds_push(fh, 1));
} } else if (EQ(str, "MAX-CHAR", len)) {
else if (EQ(str, "MAX-CHAR", len)) {
TRY(ds_push(fh, 255)); TRY(ds_push(fh, 255));
TRY(ds_push(fh, 1)); TRY(ds_push(fh, 1));
} } else if (EQ(str, "MAX-D", len)) {
else if (EQ(str, "MAX-D", len)) { TRY(ds_push_dw(fh, 0x7FFFFFFFFFFFFFFFULL));
// TODO update when double arith is properly implemented } else if (EQ(str, "MAX-UD", len)) {
TRY(ds_push(fh, 0)); TRY(ds_push_dw(fh, 0xFFFFFFFFFFFFFFFFULL));
} } else if (EQ(str, "MAX-N", len)) {
else if (EQ(str, "MAX-UD", len)) {
// TODO update when double arith is properly implemented
TRY(ds_push(fh, 0));
}
else if (EQ(str, "MAX-N", len)) {
TRY(ds_push(fh, 0x7FFFFFFFULL)); TRY(ds_push(fh, 0x7FFFFFFFULL));
TRY(ds_push(fh, 1)); TRY(ds_push(fh, 1));
} } else if (EQ(str, "MAX-U", len)) {
else if (EQ(str, "MAX-U", len)) {
TRY(ds_push(fh, 0xFFFFFFFFULL)); TRY(ds_push(fh, 0xFFFFFFFFULL));
TRY(ds_push(fh, 1)); TRY(ds_push(fh, 1));
} } else if (EQ(str, "RETURN-STACK-CELLS", len)) {
else if (EQ(str, "RETURN-STACK-CELLS", len)) {
TRY(ds_push(fh, RETURN_STACK_DEPTH)); TRY(ds_push(fh, RETURN_STACK_DEPTH));
TRY(ds_push(fh, 1)); TRY(ds_push(fh, 1));
} } else if (EQ(str, "STACK-CELLS", len)) {
else if (EQ(str, "STACK-CELLS", len)) {
TRY(ds_push(fh, DATA_STACK_DEPTH)); TRY(ds_push(fh, DATA_STACK_DEPTH));
TRY(ds_push(fh, 1)); TRY(ds_push(fh, 1));
} } else if (EQ(str, "CORE", len)) {
else if (EQ(str, "CORE", len)) {
TRY(ds_push(fh, TOBOOL(1))); TRY(ds_push(fh, TOBOOL(1)));
TRY(ds_push(fh, 1)); TRY(ds_push(fh, 1));
} } else {
else {
TRY(ds_push(fh, 0)); TRY(ds_push(fh, 0));
} }
@ -674,38 +657,38 @@ static enum fh_error w_env_query(struct fh_thread_s *fh, const struct fh_word_s
} }
const struct name_and_handler fh_builtins_meta[] = { const struct name_and_handler fh_builtins_meta[] = {
{"depth", w_depth, 0, 0}, {"depth", w_depth, 0, 0},
{"unused", w_unused, 0, 0}, {"unused", w_unused, 0, 0},
{">in", w_to_in, 0, 0}, {">in", w_to_in, 0, 0},
{">body", w_to_body, 0, 0}, {">body", w_to_body, 0, 0},
{":", w_colon, 0, 0}, {":", w_colon, 0, 0},
{":noname", w_colon_noname, 0, 0}, {":noname", w_colon_noname, 0, 0},
{"does>", w_does, 1, 0}, {"does>", w_does, 1, 0},
{";", w_semicolon, 1, 0}, {";", w_semicolon, 1, 0},
{"forget", w_forget, 1, 0}, {"forget", w_forget, 1, 0},
{"\\", w_backslash, 1, 0}, // line comment {"\\", w_backslash, 1, 0}, // line comment
{"(", w_paren, 1, 0}, // enclosed comment {"(", w_paren, 1, 0}, // enclosed comment
{"immediate", w_immediate, 0, 0}, {"immediate", w_immediate, 0, 0},
{"postpone", w_postpone, 1, 0}, {"postpone", w_postpone, 1, 0},
{"[", w_leftbracket, 1, 0}, {"[", w_leftbracket, 1, 0},
{"]", w_rightbracket, 1, 0}, {"]", w_rightbracket, 1, 0},
{"source", w_source, 0, 0}, {"source", w_source, 0, 0},
{"literal", w_literal, 1, 0}, {"literal", w_literal, 1, 0},
{"char", wp_char, 0, 0}, {"char", wp_char, 0, 0},
{"[char]", wp_char, 1, 1}, {"[char]", wp_char, 1, 1},
{"to", w_to, 1, 0}, {"to", w_to, 1, 0},
{"variable", wp_variable, 1, 0}, {"variable", wp_variable, 1, 0},
{"value", wp_variable, 1, 1}, {"value", wp_variable, 1, 1},
{"constant", wp_variable, 1, 2}, {"constant", wp_variable, 1, 2},
{"word", w_word, 0, 0}, {"word", w_word, 0, 0},
{"count", w_count, 0, 0}, {"count", w_count, 0, 0},
{"create", w_create, 0, 0}, {"create", w_create, 0, 0},
{"find", w_find, 0, 0}, {"find", w_find, 0, 0},
{"'", wp_tick, 1, 0}, {"'", wp_tick, 1, 0},
{"[']", wp_tick, 1, 1}, {"[']", wp_tick, 1, 1},
{"execute", w_execute, 0, 0}, {"execute", w_execute, 0, 0},
{"environment?", w_env_query, 0, 0}, {"environment?", w_env_query, 0, 0},
{"marker", w_marker, 0, 0}, {"marker", w_marker, 0, 0},
{"compile,", w_compile_comma, 0, 0}, {"compile,", w_compile_comma, 0, 0},
{ /* end marker */ } { /* end marker */ }
}; };

@ -230,28 +230,28 @@ static enum fh_error w_r_fetch(struct fh_thread_s *fh, const struct fh_word_s *w
const struct name_and_handler fh_builtins_stack[] = { const struct name_and_handler fh_builtins_stack[] = {
/* Stack manip */ /* Stack manip */
{"drop", w_drop, 0, 0}, {"drop", w_drop, 0, 0},
{"dup", w_dupe, 0, 0}, {"dup", w_dupe, 0, 0},
{"?dup", w_question_dupe, 0, 0}, {"?dup", w_question_dupe, 0, 0},
{"nip", w_nip, 0, 0}, {"nip", w_nip, 0, 0},
{"over", w_over, 0, 0}, {"over", w_over, 0, 0},
{"swap", w_swap, 0, 0}, {"swap", w_swap, 0, 0},
{"rot", w_rot, 0, 0}, {"rot", w_rot, 0, 0},
{"tuck", w_tuck, 0, 0}, {"tuck", w_tuck, 0, 0},
{"pick", w_pick, 0, 0}, {"pick", w_pick, 0, 0},
{"roll", w_roll, 0, 0}, {"roll", w_roll, 0, 0},
/* Double wide stack manip */ /* Double wide stack manip */
{"2drop", w_two_drop, 0, 0}, {"2drop", w_two_drop, 0, 0},
{"2dup", w_two_dup, 0, 0}, {"2dup", w_two_dup, 0, 0},
{"2over", w_two_over, 0, 0}, {"2over", w_two_over, 0, 0},
{"2swap", w_two_swap, 0, 0}, {"2swap", w_two_swap, 0, 0},
/* Return stack manip */ /* Return stack manip */
{">r", w_to_r, 0, 0}, {">r", w_to_r, 0, 0},
{"r>", w_r_from, 0, 0}, {"r>", w_r_from, 0, 0},
{"r@", w_r_fetch, 0, 0}, {"r@", w_r_fetch, 0, 0},
/* Double wide return stack manip */ /* Double wide return stack manip */
{"2>r", w_two_to_r, 0, 0}, {"2>r", w_two_to_r, 0, 0},
{"2r>", w_two_r_from, 0, 0}, {"2r>", w_two_r_from, 0, 0},
{"2r@", w_two_r_fetch, 0, 0}, {"2r@", w_two_r_fetch, 0, 0},
{ /* end marker */ } { /* end marker */ }
}; };

@ -38,10 +38,10 @@ static enum fh_error w_exit(struct fh_thread_s *fh, const struct fh_word_s *w)
} }
const struct name_and_handler fh_builtins_system[] = { const struct name_and_handler fh_builtins_system[] = {
{"reset", w_reset, 1, 0}, {"reset", w_reset, 1, 0},
{"bye", w_bye, 0, 0}, {"bye", w_bye, 0, 0},
{"debug", w_debug, 0, 0}, {"debug", w_debug, 0, 0},
{"exit", w_exit, 1, 0}, {"exit", w_exit, 1, 0},
{ /* end marker */ } { /* end marker */ }
}; };

@ -8,7 +8,7 @@ static enum fh_error pop_addr_len(struct fh_thread_s *fh, uint32_t *addr, uint32
if (*addr >= HEAP_SIZE) { // not HEAP_END, because this can point into other buffers too if (*addr >= HEAP_SIZE) { // not HEAP_END, because this can point into other buffers too
LOGE("heap string pointer out of bounds!"); LOGE("heap string pointer out of bounds!");
return FH_ERR_NOT_APPLICABLE; // TODO better code return FH_ERR_ILLEGAL_FETCH;
} }
return FH_OK; return FH_OK;
} }
@ -81,7 +81,6 @@ static enum fh_error w_dot(struct fh_thread_s *fh, const struct fh_word_s *w)
} }
static enum fh_error w_dot_r(struct fh_thread_s *fh, const struct fh_word_s *w) static enum fh_error w_dot_r(struct fh_thread_s *fh, const struct fh_word_s *w)
{ {
(void) w; (void) w;
@ -124,7 +123,7 @@ static enum fh_error w_type(struct fh_thread_s *fh, const struct fh_word_s *w)
uint32_t count = 0, addr = 0; uint32_t count = 0, addr = 0;
TRY(pop_addr_len(fh, &addr, &count)); TRY(pop_addr_len(fh, &addr, &count));
const char *str = fh_str_at(fh, addr); const char *str = fh_str_at(fh, addr);
if (!str) return FH_ERR_INTERNAL; if (!str) { return FH_ERR_INTERNAL; }
FHPRINT("%.*s", count, str); FHPRINT("%.*s", count, str);
return FH_OK; return FH_OK;
} }
@ -137,9 +136,9 @@ static enum fh_error w_fill(struct fh_thread_s *fh, const struct fh_word_s *w)
TRY(ds_pop(fh, &ch)); TRY(ds_pop(fh, &ch));
TRY(pop_addr_len(fh, &addr, &count)); TRY(pop_addr_len(fh, &addr, &count));
const char *str = fh_str_at(fh, addr); const char *str = fh_str_at(fh, addr);
if (!str) return FH_ERR_INTERNAL; if (!str) { return FH_ERR_INTERNAL; }
if (count > 0) { if (count > 0) {
memset((void*)str, (uint8_t)ch, count); memset((void *) str, (uint8_t) ch, count);
} }
return FH_OK; return FH_OK;
} }
@ -185,6 +184,7 @@ static enum fh_error w_emit(struct fh_thread_s *fh, const struct fh_word_s *w)
static enum fh_error w_see(struct fh_thread_s *fh, const struct fh_word_s *w) static enum fh_error w_see(struct fh_thread_s *fh, const struct fh_word_s *w)
{ {
(void) w;
enum fh_error rv; enum fh_error rv;
char *wordname; char *wordname;
size_t namelen = 0; size_t namelen = 0;
@ -210,10 +210,10 @@ static enum fh_error w_s_quote(struct fh_thread_s *fh, const struct fh_word_s *w
struct fh_instruction_s instr; struct fh_instruction_s instr;
if (fh->state == FH_STATE_INTERPRET) { if (fh->state == FH_STATE_INTERPRET) {
LOG("Interpret a string alloc: \"%.*s\"", len, start); LOG("Interpret a string alloc: \"%.*s\"", (int) len, start);
TRY(push_addr_len(fh, addr, len)); TRY(push_addr_len(fh, addr, len));
} else { } else {
LOG("Compile a string: \"%.*s\"", len, start); LOG("Compile a string: \"%.*s\"", (int) len, start);
instr.kind = FH_INSTR_ALLOCSTR; instr.kind = FH_INSTR_ALLOCSTR;
instr.data = len; instr.data = len;
fh_heap_write(fh, addr - INSTR_SIZE, &instr, INSTR_SIZE); fh_heap_write(fh, addr - INSTR_SIZE, &instr, INSTR_SIZE);
@ -234,7 +234,7 @@ static enum fh_error w_c_quote(struct fh_thread_s *fh, const struct fh_word_s *w
fh_input_consume_spaces(fh); fh_input_consume_spaces(fh);
char *start = ((char *) &fh->heap[addr]) + 1; // space for the counter char *start = ((char *) &fh->heap[addr]) + 1; // space for the counter
uint32_t maxlen = HEAP_END - addr; uint32_t maxlen = HEAP_END - addr;
if (maxlen > 255) { if (maxlen > 255) {
maxlen = 255; maxlen = 255;
} }
TRY(fh_input_read_quotedstring(fh, w->param == 1, start, maxlen, &len)); TRY(fh_input_read_quotedstring(fh, w->param == 1, start, maxlen, &len));
@ -243,10 +243,10 @@ static enum fh_error w_c_quote(struct fh_thread_s *fh, const struct fh_word_s *w
struct fh_instruction_s instr; struct fh_instruction_s instr;
if (fh->state == FH_STATE_INTERPRET) { if (fh->state == FH_STATE_INTERPRET) {
LOG("Interpret a c-string alloc: \"%.*s\"", len, start); LOG("Interpret a c-string alloc: \"%.*s\"", (int) len, start);
TRY(ds_push(fh, addr)); TRY(ds_push(fh, addr));
} else { } else {
LOG("Compile a c-string: \"%.*s\"", len, start); LOG("Compile a c-string: \"%.*s\"", (int) len, start);
instr.kind = FH_INSTR_ALLOCSTR_C; instr.kind = FH_INSTR_ALLOCSTR_C;
instr.data = WORDALIGNED(len + 1); instr.data = WORDALIGNED(len + 1);
fh_heap_write(fh, addr - INSTR_SIZE, &instr, INSTR_SIZE); fh_heap_write(fh, addr - INSTR_SIZE, &instr, INSTR_SIZE);
@ -257,7 +257,7 @@ static enum fh_error w_c_quote(struct fh_thread_s *fh, const struct fh_word_s *w
static bool chartest_equals_or_end(char c, void *param) static bool chartest_equals_or_end(char c, void *param)
{ {
char cc = *(char*)param; char cc = *(char *) param;
return cc == c || c == 0; return cc == c || c == 0;
} }
@ -274,7 +274,7 @@ static enum fh_error w_dot_quote(struct fh_thread_s *fh, const struct fh_word_s
fh_input_consume_spaces(fh); fh_input_consume_spaces(fh);
char *start; char *start;
char c = (char)w->param; char c = (char) w->param;
uint32_t capacity = HEAP_END - addr; uint32_t capacity = HEAP_END - addr;
LOG("dotquote end: %c", c); LOG("dotquote end: %c", c);
if (c == '\\') { if (c == '\\') {
@ -292,12 +292,11 @@ static enum fh_error w_dot_quote(struct fh_thread_s *fh, const struct fh_word_s
} }
} }
struct fh_instruction_s instr;
if (fh->state == FH_STATE_INTERPRET) { if (fh->state == FH_STATE_INTERPRET) {
FHPRINT("%.*s", (int) len, start); FHPRINT("%.*s", (int) len, start);
// the string is invalidated immediately, heap pointer is NOT advanced. // the string is invalidated immediately, heap pointer is NOT advanced.
} else { } else {
LOG("Compile a string: \"%.*s\"", len, start); LOG("Compile a string: \"%.*s\"", (int) len, start);
TRY(fh_put_instr(fh, FH_INSTR_TYPESTR, len)); TRY(fh_put_instr(fh, FH_INSTR_TYPESTR, len));
fh->here = WORDALIGNED(addr + len); // at the end of the string fh->here = WORDALIGNED(addr + len); // at the end of the string
} }
@ -308,7 +307,6 @@ static enum fh_error w_dot_quote(struct fh_thread_s *fh, const struct fh_word_s
static enum fh_error w_less_hash(struct fh_thread_s *fh, const struct fh_word_s *w) static enum fh_error w_less_hash(struct fh_thread_s *fh, const struct fh_word_s *w)
{ {
(void) w; (void) w;
enum fh_error rv;
fh->pictnumptr = WORDBUF_LASTCHAR_ADDR; fh->pictnumptr = WORDBUF_LASTCHAR_ADDR;
return FH_OK; return FH_OK;
} }
@ -317,21 +315,21 @@ static enum fh_error w_hash_greater(struct fh_thread_s *fh, const struct fh_word
{ {
(void) w; (void) w;
enum fh_error rv; enum fh_error rv;
uint64_t dummy; uint64_t dummy;
TRY(ds_pop_dw(fh, &dummy)); TRY(ds_pop_dw(fh, &dummy));
uint32_t len = WORDBUF_LASTCHAR_ADDR - fh->pictnumptr; uint32_t len = WORDBUF_LASTCHAR_ADDR - fh->pictnumptr;
uint32_t addr; uint32_t addr;
TRY(fh_heap_reserve(fh, len, &addr)); TRY(fh_heap_reserve(fh, len, &addr));
fh_heap_copy(fh, addr, fh->pictnumptr+1, len); fh_heap_copy(fh, addr, fh->pictnumptr + 1, len);
LOG("#> output: \"%.*s\"", len, &fh->heap[fh->pictnumptr+1]); LOG("#> output: \"%.*s\"", len, &fh->heap[fh->pictnumptr + 1]);
TRY(push_addr_len(fh, addr, len)); TRY(push_addr_len(fh, addr, len));
return FH_OK; return FH_OK;
} }
static enum fh_error pictnum_prepend_char(struct fh_thread_s *fh, char c) { static enum fh_error pictnum_prepend_char(struct fh_thread_s *fh, char c)
{
enum fh_error rv; enum fh_error rv;
if (fh->pictnumptr < WORDBUF_ADDR) { if (fh->pictnumptr < WORDBUF_ADDR) {
return FH_ERR_PICTNUM_FULL; return FH_ERR_PICTNUM_FULL;
@ -342,27 +340,29 @@ static enum fh_error pictnum_prepend_char(struct fh_thread_s *fh, char c) {
return FH_OK; return FH_OK;
} }
static char dig2char(uint64_t digit) { static char dig2char(uint64_t digit)
{
char repr; char repr;
if (digit < 10) { if (digit < 10) {
repr = '0' + digit; repr = (char)('0' + (char)digit);
} else if (digit < 36) { } else if (digit < 36) {
repr = 'A' + (digit - 10); repr = (char)('A' + ((char)digit - 10));
} else { } else {
repr = '?'; // XXX bad base? // This shouldn't happen
repr = '?';
} }
return repr; return repr;
} }
static enum fh_error w_hash(struct fh_thread_s *fh, const struct fh_word_s *w) static enum fh_error w_hash(struct fh_thread_s *fh, const struct fh_word_s *w)
{ {
(void) w; (void) w;
enum fh_error rv; enum fh_error rv;
uint64_t num; uint64_t num;
TRY(ds_pop_dw(fh, &num)); TRY(ds_pop_dw(fh, &num));
uint64_t digit = num % fh->base; uint64_t digit = num % fh->base;
TRY(pictnum_prepend_char(fh, dig2char(digit))); TRY(pictnum_prepend_char(fh, dig2char(digit)));
TRY(ds_push_dw(fh, num / (uint64_t)fh->base)); TRY(ds_push_dw(fh, num / (uint64_t) fh->base));
return FH_OK; return FH_OK;
} }
@ -372,13 +372,13 @@ static enum fh_error w_hash_s(struct fh_thread_s *fh, const struct fh_word_s *w)
enum fh_error rv; enum fh_error rv;
uint64_t num; uint64_t num;
TRY(ds_pop_dw(fh, &num)); TRY(ds_pop_dw(fh, &num));
do { do {
uint64_t digit = num % fh->base; uint64_t digit = num % fh->base;
num = num / (uint64_t)fh->base; num = num / (uint64_t) fh->base;
TRY(pictnum_prepend_char(fh, dig2char(digit))); TRY(pictnum_prepend_char(fh, dig2char(digit)));
} while (num > 0); } while (num > 0);
TRY(ds_push_dw(fh, num)); // this is zero now TRY(ds_push_dw(fh, num)); // this is zero now
return FH_OK; return FH_OK;
} }
@ -389,7 +389,7 @@ static enum fh_error w_sign(struct fh_thread_s *fh, const struct fh_word_s *w)
enum fh_error rv; enum fh_error rv;
uint32_t num; uint32_t num;
TRY(ds_pop(fh, &num)); TRY(ds_pop(fh, &num));
if ((int32_t)num < 0) { if ((int32_t) num < 0) {
TRY(pictnum_prepend_char(fh, '-')); TRY(pictnum_prepend_char(fh, '-'));
} }
return FH_OK; return FH_OK;
@ -401,10 +401,10 @@ static enum fh_error w_hold(struct fh_thread_s *fh, const struct fh_word_s *w)
enum fh_error rv; enum fh_error rv;
uint32_t ch; uint32_t ch;
TRY(ds_pop(fh, &ch)); TRY(ds_pop(fh, &ch));
char buf[5]; char buf[5];
int num = utf8_encode(buf, ch); int num = utf8_encode(buf, ch);
for(int i=num-1;i>=0;i--) { for (int i = num - 1; i >= 0; i--) {
TRY(pictnum_prepend_char(fh, buf[i])); TRY(pictnum_prepend_char(fh, buf[i]));
} }
return FH_OK; return FH_OK;
@ -417,12 +417,12 @@ static enum fh_error w_holds(struct fh_thread_s *fh, const struct fh_word_s *w)
uint32_t count = 0, addr = 0; uint32_t count = 0, addr = 0;
TRY(pop_addr_len(fh, &addr, &count)); TRY(pop_addr_len(fh, &addr, &count));
const char *str = fh_str_at(fh, addr); const char *str = fh_str_at(fh, addr);
if (!str) return FH_ERR_INTERNAL; if (!str) { return FH_ERR_INTERNAL; }
for(int i=count-1; i>=0; i--) { for (int i = (int)count - 1; i >= 0; i--) {
TRY(pictnum_prepend_char(fh, str[i])); TRY(pictnum_prepend_char(fh, str[i]));
} }
return FH_OK; return FH_OK;
} }
@ -432,7 +432,7 @@ static enum fh_error w_spaces(struct fh_thread_s *fh, const struct fh_word_s *w)
enum fh_error rv; enum fh_error rv;
uint32_t num; uint32_t num;
TRY(ds_pop(fh, &num)); TRY(ds_pop(fh, &num));
while(num-->0) { while (num-- > 0) {
FHPRINT(" "); FHPRINT(" ");
} }
return FH_OK; return FH_OK;
@ -442,25 +442,25 @@ static enum fh_error w_to_number(struct fh_thread_s *fh, const struct fh_word_s
{ {
(void) w; (void) w;
enum fh_error rv; enum fh_error rv;
/* /*
( ud1 c-addr1 u1 -- ud2 c-addr2 u2 ) ( ud1 c-addr1 u1 -- ud2 c-addr2 u2 )
ud2 is the unsigned result of converting the characters within the string specified by c-addr1 u1 into digits, using the number in BASE, and adding each into ud1 after multiplying ud1 by the number in BASE. Conversion continues left-to-right until a character that is not convertible, including any "+" or "-", is encountered or the string is entirely converted. c-addr2 is the location of the first unconverted character or the first character past the end of the string if the string was entirely converted. u2 is the number of unconverted characters in the string. An ambiguous condition exists if ud2 overflows during the conversion. ud2 is the unsigned result of converting the characters within the string specified by c-addr1 u1 into digits, using the number in BASE, and adding each into ud1 after multiplying ud1 by the number in BASE. Conversion continues left-to-right until a character that is not convertible, including any "+" or "-", is encountered or the string is entirely converted. c-addr2 is the location of the first unconverted character or the first character past the end of the string if the string was entirely converted. u2 is the number of unconverted characters in the string. An ambiguous condition exists if ud2 overflows during the conversion.
*/ */
uint32_t count = 0, addr = 0; uint32_t count = 0, addr = 0;
TRY(pop_addr_len(fh, &addr, &count)); TRY(pop_addr_len(fh, &addr, &count));
const char *str = fh_str_at(fh, addr); const char *str = fh_str_at(fh, addr);
if (!str) return FH_ERR_INTERNAL; if (!str) { return FH_ERR_INTERNAL; }
LOG("parse num from str: %.*s", count, str); LOG("parse num from str: %.*s", count, str);
uint64_t val; uint64_t val;
TRY(ds_pop_dw(fh, &val)); TRY(ds_pop_dw(fh, &val));
int conv; int conv;
int i = 0; int i = 0;
for(; i<count; i++) { for (; i < count; i++) {
char ch = str[i]; char ch = str[i];
LOG("parse c: %c", ch); LOG("parse c: %c", ch);
if (ch >= '0' && ch <= '9') { if (ch >= '0' && ch <= '9') {
@ -472,48 +472,48 @@ static enum fh_error w_to_number(struct fh_thread_s *fh, const struct fh_word_s
} else { } else {
break; break;
} }
if (conv >= fh->base) { if (conv >= fh->base) {
LOG("not numeric, end num parse!"); LOG("not numeric, end num parse!");
break; break;
} }
val = (val * (uint64_t)fh->base) + (uint64_t)conv; val = (val * (uint64_t) fh->base) + (uint64_t) conv;
} }
LOG("parsed num: %d", val); LOG("parsed num: %d", (int)val);
TRY(ds_push_dw(fh, val)); TRY(ds_push_dw(fh, val));
TRY(push_addr_len(fh, addr+i, count-i)); TRY(push_addr_len(fh, addr + i, count - i));
return FH_OK; return FH_OK;
} }
const struct name_and_handler fh_builtins_text[] = { const struct name_and_handler fh_builtins_text[] = {
{"s\"", w_s_quote, 1, 0}, {"s\"", w_s_quote, 1, 0},
{"c\"", w_c_quote, 1, 0}, {"c\"", w_c_quote, 1, 0},
{"s\\\"", w_s_quote, 1, 1}, // escaped {"s\\\"", w_s_quote, 1, 1}, // escaped
{".\"", w_dot_quote, 1, '"'}, {".\"", w_dot_quote, 1, '"'},
{".(", w_dot_quote, 1, ')'}, {".(", w_dot_quote, 1, ')'},
{".\\\"", w_dot_quote, 1, '\\'}, // escaped, this is non-standard {".\\\"", w_dot_quote, 1, '\\'}, // escaped, this is non-standard
{".", w_dot, 0, 0}, {".", w_dot, 0, 0},
{".r", w_dot_r, 0, 0}, {".r", w_dot_r, 0, 0},
{"u.", w_u_dot, 0, 0}, {"u.", w_u_dot, 0, 0},
{"type", w_type, 0, 0}, {"type", w_type, 0, 0},
{"fill", w_fill, 0, 0}, {"fill", w_fill, 0, 0},
{"cr", wp_putc, 0, '\n'}, {"cr", wp_putc, 0, '\n'},
{"space", wp_putc, 0, ' '}, {"space", wp_putc, 0, ' '},
{"spaces", w_spaces, 0, 0}, {"spaces", w_spaces, 0, 0},
{"bl", wp_const, 0, ' '}, {"bl", wp_const, 0, ' '},
{"u.r", w_u_r, 0, 0}, {"u.r", w_u_r, 0, 0},
{"??", w_debug_dump, 0, 0}, // XXX non-standard {"??", w_debug_dump, 0, 0}, // XXX non-standard
{"emit", w_emit, 0, 0}, {"emit", w_emit, 0, 0},
{"see", w_see, 0, 0}, {"see", w_see, 0, 0},
{"<#", w_less_hash, 0, 0}, {"<#", w_less_hash, 0, 0},
{"#>", w_hash_greater, 0, 0}, {"#>", w_hash_greater, 0, 0},
{"#", w_hash, 0, 0}, {"#", w_hash, 0, 0},
{"#s", w_hash_s, 0, 0}, {"#s", w_hash_s, 0, 0},
{"sign", w_sign, 0, 0}, {"sign", w_sign, 0, 0},
{"hold", w_hold, 0, 0}, {"hold", w_hold, 0, 0},
{"holds", w_holds, 0, 0}, {"holds", w_holds, 0, 0},
{">number", w_to_number, 0, 0}, {">number", w_to_number, 0, 0},
{ /* end marker */ } { /* end marker */ }
}; };

@ -7,7 +7,7 @@ void fh_fill_input_buffer(struct fh_thread_s *fh, const char *data, size_t num)
{ {
assert(num <= INPUT_BUFFER_SIZE); assert(num <= INPUT_BUFFER_SIZE);
memcpy(&fh->heap[INPUTBUF_ADDR], data, num); memcpy(&fh->heap[INPUTBUF_ADDR], data, num);
fh->heap[INPUTBUF_ADDR+num] = 0; // terminator fh->heap[INPUTBUF_ADDR + num] = 0; // terminator
fh->inputptr = 0; fh->inputptr = 0;
fh->inputlen = num; fh->inputlen = num;
} }
@ -17,7 +17,8 @@ void fh_align(struct fh_thread_s *fh)
fh->here = WORDALIGNED(fh->here); fh->here = WORDALIGNED(fh->here);
} }
void fh_setbase(struct fh_thread_s *fh, uint32_t base) { void fh_setbase(struct fh_thread_s *fh, uint32_t base)
{
LOG("set BASE = %d", base); LOG("set BASE = %d", base);
fh->base = base; fh->base = base;
} }
@ -36,7 +37,7 @@ enum fh_error fh_fetch(struct fh_thread_s *fh, uint32_t addr, uint32_t *dst)
break; break;
case MAGICADDR_STATE: case MAGICADDR_STATE:
*dst = TOBOOL(fh->state==FH_STATE_COMPILE); *dst = TOBOOL(fh->state == FH_STATE_COMPILE);
LOG("Fetch state %d", *dst); LOG("Fetch state %d", *dst);
break; break;
@ -51,7 +52,7 @@ enum fh_error fh_fetch(struct fh_thread_s *fh, uint32_t addr, uint32_t *dst)
return FH_ERR_ILLEGAL_FETCH; return FH_ERR_ILLEGAL_FETCH;
} }
if (addr < HEAP_SIZE - 4) { if (addr < HEAP_SIZE - 4) {
*dst = *((uint32_t*)&fh->heap[addr]); *dst = *((uint32_t *) &fh->heap[addr]);
} else { } else {
LOGE("Address 0x%08x too high!", addr); LOGE("Address 0x%08x too high!", addr);
return FH_ERR_ILLEGAL_FETCH; return FH_ERR_ILLEGAL_FETCH;
@ -100,8 +101,8 @@ enum fh_error fh_store(struct fh_thread_s *fh, uint32_t addr, uint32_t val)
return FH_ERR_ILLEGAL_STORE; return FH_ERR_ILLEGAL_STORE;
} }
if (addr <= HEAP_SIZE - 4) { if (addr <= HEAP_SIZE - 4) {
LOG("Store 0x%08x int %d", addr, (int)val); LOG("Store 0x%08x int %d", addr, (int) val);
*((uint32_t*)&fh->heap[addr]) = val; *((uint32_t *) &fh->heap[addr]) = val;
} else { } else {
LOGE("Address 0x%08x too high!", addr); LOGE("Address 0x%08x too high!", addr);
return FH_ERR_ILLEGAL_STORE; return FH_ERR_ILLEGAL_STORE;
@ -158,14 +159,15 @@ void fh_heap_write(struct fh_thread_s *fh, uint32_t addr, const void *src, uint3
memcpy(&fh->heap[addr], src, len); memcpy(&fh->heap[addr], src, len);
} }
enum fh_error fh_put_instr(struct fh_thread_s *fh, enum fh_instruction_kind kind, uint32_t data) { enum fh_error fh_put_instr(struct fh_thread_s *fh, enum fh_instruction_kind kind, uint32_t data)
{
fh_align(fh); fh_align(fh);
struct fh_instruction_s instr = { struct fh_instruction_s instr = {
.kind = kind, .kind = kind,
.data = data, .data = data,
}; };
LOG("\x1b[90mAppend instr %s, data 0x%08x at 0x%08x\x1b[m", instr_name(kind), data, fh->here); LOG("\x1b[90mAppend instr %s, data 0x%08x at 0x%08x\x1b[m", instr_name(kind), data, (uint32_t) fh->here);
return fh_heap_put(fh, &instr, INSTR_SIZE); return fh_heap_put(fh, &instr, INSTR_SIZE);
} }
@ -187,13 +189,14 @@ void fh_heap_copy(struct fh_thread_s *fh, uint32_t addr, uint32_t srcaddr, uint3
} }
/** Copy bytes from anywhere to heap. The region must have been previously allocated! */ /** Copy bytes from anywhere to heap. The region must have been previously allocated! */
void fh_heap_copyptr(struct fh_thread_s *fh, uint32_t addr, char * source, uint32_t len) void fh_heap_copyptr(struct fh_thread_s *fh, uint32_t addr, char *source, uint32_t len)
{ {
memcpy(&fh->heap[addr], source, len); memcpy(&fh->heap[addr], source, len);
} }
char *fh_str_at(struct fh_thread_s *fh, uint32_t addr) { char *fh_str_at(struct fh_thread_s *fh, uint32_t addr)
{
if (addr >= HEAP_SIZE) { if (addr >= HEAP_SIZE) {
LOGE("fh_str_at out of bounds! 0x%08x", addr); LOGE("fh_str_at out of bounds! 0x%08x", addr);
return NULL; return NULL;
@ -201,7 +204,8 @@ char *fh_str_at(struct fh_thread_s *fh, uint32_t addr) {
return (char *) &fh->heap[addr]; return (char *) &fh->heap[addr];
} }
struct fh_instruction_s *fh_instr_at(struct fh_thread_s *fh, uint32_t addr) { struct fh_instruction_s *fh_instr_at(struct fh_thread_s *fh, uint32_t addr)
{
if (addr >= HEAP_END) { if (addr >= HEAP_END) {
LOGE("fh_instr_at out of bounds! 0x%08x", addr); LOGE("fh_instr_at out of bounds! 0x%08x", addr);
return NULL; return NULL;
@ -209,7 +213,8 @@ struct fh_instruction_s *fh_instr_at(struct fh_thread_s *fh, uint32_t addr) {
return (void *) &fh->heap[addr]; return (void *) &fh->heap[addr];
} }
struct fh_word_s *fh_word_at(struct fh_thread_s *fh, uint32_t addr) { struct fh_word_s *fh_word_at(struct fh_thread_s *fh, uint32_t addr)
{
if (addr >= HEAP_END) { if (addr >= HEAP_END) {
LOGE("fh_word_at out of bounds! 0x%08x", addr); LOGE("fh_word_at out of bounds! 0x%08x", addr);
return NULL; return NULL;

@ -42,7 +42,7 @@ enum fh_error fh_handle_ascii_word(
} }
} }
long v = strtol(name, &endptr, base); // XXX if base is 0, this will use auto-detection long v = strtol(name, &endptr, base); // if base is 0, this will use auto-detection
if (errno != 0 || (endptr - name) != wordlen) { if (errno != 0 || (endptr - name) != wordlen) {
LOGE("Unknown word and fail to parse as number: \"%.*s\"", (int) wordlen, name); LOGE("Unknown word and fail to parse as number: \"%.*s\"", (int) wordlen, name);
return FH_ERR_UNKNOWN_WORD; return FH_ERR_UNKNOWN_WORD;
@ -61,7 +61,8 @@ enum fh_error fh_handle_ascii_word(
} }
void fh_input_consume_matching(struct fh_thread_s *fh, chartest_t test, void* param) { void fh_input_consume_matching(struct fh_thread_s *fh, chartest_t test, void *param)
{
char *rp = (char *) &fh->heap[INPUTBUF_ADDR + fh->inputptr]; char *rp = (char *) &fh->heap[INPUTBUF_ADDR + fh->inputptr];
while (test(*rp, param)) { while (test(*rp, param)) {
rp++; rp++;
@ -69,7 +70,8 @@ void fh_input_consume_matching(struct fh_thread_s *fh, chartest_t test, void* pa
} }
} }
void fh_input_consume_spaces(struct fh_thread_s *fh) { void fh_input_consume_spaces(struct fh_thread_s *fh)
{
char *rp = (char *) &fh->heap[INPUTBUF_ADDR + fh->inputptr]; char *rp = (char *) &fh->heap[INPUTBUF_ADDR + fh->inputptr];
while (isspace(*rp)) { while (isspace(*rp)) {
rp++; rp++;
@ -77,7 +79,7 @@ void fh_input_consume_spaces(struct fh_thread_s *fh) {
} }
} }
enum fh_error fh_input_read_delimited(struct fh_thread_s *fh, char **out, size_t *len, chartest_t test, void* param) enum fh_error fh_input_read_delimited(struct fh_thread_s *fh, char **out, size_t *len, chartest_t test, void *param)
{ {
char *rp = (char *) &fh->heap[INPUTBUF_ADDR + fh->inputptr]; char *rp = (char *) &fh->heap[INPUTBUF_ADDR + fh->inputptr];
char *start = rp; char *start = rp;
@ -100,15 +102,17 @@ enum fh_error fh_input_read_delimited(struct fh_thread_s *fh, char **out, size_t
static bool chartest_space_or_end(char c, void *param) static bool chartest_space_or_end(char c, void *param)
{ {
(void)param; (void) param;
return isspace(c) || c == 0; return isspace(c) || c == 0;
} }
enum fh_error fh_input_read_word(struct fh_thread_s *fh, char **out, size_t *len) { enum fh_error fh_input_read_word(struct fh_thread_s *fh, char **out, size_t *len)
{
return fh_input_read_delimited(fh, out, len, chartest_space_or_end, NULL); return fh_input_read_delimited(fh, out, len, chartest_space_or_end, NULL);
} }
enum fh_error fh_input_read_quotedstring(struct fh_thread_s *fh, bool escaped, char *outbuf, size_t capacity, size_t *out_len) { enum fh_error fh_input_read_quotedstring(struct fh_thread_s *fh, bool escaped, char *outbuf, size_t capacity, size_t *out_len)
{
char *rp = (char *) &fh->heap[INPUTBUF_ADDR + fh->inputptr]; char *rp = (char *) &fh->heap[INPUTBUF_ADDR + fh->inputptr];
bool next_escaped = false; bool next_escaped = false;
size_t remains = capacity; size_t remains = capacity;
@ -126,9 +130,9 @@ enum fh_error fh_input_read_quotedstring(struct fh_thread_s *fh, bool escaped, c
hex <<= 4; hex <<= 4;
if (isdigit(c)) { if (isdigit(c)) {
hex |= c - '0'; hex |= c - '0';
} else if (c>='a' && c<='f') { } else if (c >= 'a' && c <= 'f') {
hex |= c - 'a'; hex |= c - 'a';
} else if (c>='A' && c<='F') { } else if (c >= 'A' && c <= 'F') {
hex |= c - 'A'; hex |= c - 'A';
} else { } else {
LOGE("Bad hex escape"); LOGE("Bad hex escape");
@ -157,24 +161,44 @@ enum fh_error fh_input_read_quotedstring(struct fh_thread_s *fh, bool escaped, c
} else { } else {
next_escaped = false; next_escaped = false;
switch (c) { switch (c) {
case 'a': c = 7; break; case 'a':
case 'b': c = 8; break; c = 7;
case 'e': c = 27; break; break;
case 'f': c = 12; break; case 'b':
case 'l': c = 10; break; c = 8;
break;
case 'e':
c = 27;
break;
case 'f':
c = 12;
break;
case 'l':
c = 10;
break;
case 'm': case 'm':
case 'n': case 'n':
if (remains < 2) goto full; if (remains < 2) { goto full; }
*outbuf++ = '\r'; *outbuf++ = '\r';
*outbuf++ = '\n'; *outbuf++ = '\n';
remains -= 2; remains -= 2;
len += 2; len += 2;
goto skip; goto skip;
case 'q': c = '"'; break; case 'q':
case 'r': c = '\r'; break; c = '"';
case 't': c = '\t'; break; break;
case 'v': c = '\v'; break; case 'r':
case 'z': c = 0; break; // XXX this will cause problems! c = '\r';
break;
case 't':
c = '\t';
break;
case 'v':
c = '\v';
break;
case 'z':
c = 0;
break; // this will cause problems with string printing
case 'x': case 'x':
hex = 0; hex = 0;
hexdigits = 2; hexdigits = 2;
@ -226,7 +250,7 @@ enum fh_error fh_process_line(struct fh_thread_s *fh, const char *linebuf, size_
continue; continue;
} }
const char * const rp = ReadPtr; const char *const rp = ReadPtr;
char *end; char *end;
size_t length; size_t length;
@ -280,11 +304,11 @@ enum fh_error fh_process_line(struct fh_thread_s *fh, const char *linebuf, size_
} else { } else {
if (EQ(rp, "\\", length)) { if (EQ(rp, "\\", length)) {
// discard to EOL // discard to EOL
LOG("Discard \"%.*s\"", fh->inputlen - fh->inputptr + length, rp); LOG("Discard \"%.*s\"", (int)(fh->inputlen - fh->inputptr + length), rp);
goto done; goto done;
} }
LOG("Discard \"%.*s\"", length, rp); LOG("Discard \"%.*s\"", (int) length, rp);
} }
if (!end) { if (!end) {
@ -296,7 +320,7 @@ enum fh_error fh_process_line(struct fh_thread_s *fh, const char *linebuf, size_
end = strchr(rp, ')'); end = strchr(rp, ')');
if (end) { if (end) {
length = end - rp; length = end - rp;
LOG("Discard inline comment: \"%.*s\"", length, rp); LOG("Discard inline comment: \"%.*s\"", (int)length, rp);
fh_setsubstate(fh, FH_SUBSTATE_NONE); fh_setsubstate(fh, FH_SUBSTATE_NONE);
ReadPos += length + 1; ReadPos += length + 1;
} else { } else {

@ -46,7 +46,8 @@ static const char *instrnames[FH_INSTR_MAX] = {
}; };
const char *instr_name(enum fh_instruction_kind kind) { const char *instr_name(enum fh_instruction_kind kind)
{
if (kind >= FH_INSTR_MAX) { if (kind >= FH_INSTR_MAX) {
return "Unknown"; return "Unknown";
} else { } else {
@ -68,7 +69,7 @@ enum fh_error fh_add_word(const struct fh_word_s *w, struct fh_thread_s *fh)
// thread it onto the linked list // thread it onto the linked list
struct fh_word_s *word = fh_word_at(fh, ptr); struct fh_word_s *word = fh_word_at(fh, ptr);
if (!word) return FH_ERR_INTERNAL; if (!word) { return FH_ERR_INTERNAL; }
word->previous = fh->dict_last; word->previous = fh->dict_last;
fh->dict_last = ptr; fh->dict_last = ptr;
@ -117,7 +118,7 @@ enum fh_error w_user_word(struct fh_thread_s *fh, const struct fh_word_s *w0)
TRY(rs_push(fh, fh->execptr)); TRY(rs_push(fh, fh->execptr));
fh->execptr = w->param; fh->execptr = w->param;
if ((WORDFLAG_WORD | WORDFLAG_CREATED) == (w->flags & (WORDFLAG_WORD | WORDFLAG_CREATED))) { if ((WORDFLAG_WORD | WORDFLAG_CREATED) == (w->flags & (WORDFLAG_WORD | WORDFLAG_CREATED))) {
// push the >BODY addr if this is a CREATE'd word // push the >BODY addr if this is a CREATE'd word
TRY(ds_push(fh, word_addr(fh, w) + DICTWORD_SIZE)); TRY(ds_push(fh, word_addr(fh, w) + DICTWORD_SIZE));
@ -151,13 +152,13 @@ enum fh_error w_user_word(struct fh_thread_s *fh, const struct fh_word_s *w0)
case FH_INSTR_POSTPONED_WORD: case FH_INSTR_POSTPONED_WORD:
//if (fh->state == FH_STATE_COMPILE) { //if (fh->state == FH_STATE_COMPILE) {
w2 = fh_word_at(fh, instr->data); w2 = fh_word_at(fh, instr->data);
if (!w2) { if (!w2) {
LOGE("Postponed bad word addr!"); LOGE("Postponed bad word addr!");
return FH_ERR_INTERNAL; return FH_ERR_INTERNAL;
} }
if (w2->flags & WORDFLAG_IMMEDIATE) { if (w2->flags & WORDFLAG_IMMEDIATE) {
goto call_w2; goto call_w2;
// LOG("Call immediate postponed word: %s", w2->name); // LOG("Call immediate postponed word: %s", w2->name);
// if (w2->flags & WORDFLAG_BUILTIN) { // if (w2->flags & WORDFLAG_BUILTIN) {
// TRY(rs_push(fh, fh->execptr)); // TRY(rs_push(fh, fh->execptr));
@ -166,10 +167,10 @@ enum fh_error w_user_word(struct fh_thread_s *fh, const struct fh_word_s *w0)
// if (0 == (w2->flags & WORDFLAG_BUILTIN)) { // if (0 == (w2->flags & WORDFLAG_BUILTIN)) {
// TRY(rs_pop(fh, &fh->execptr)); // TRY(rs_pop(fh, &fh->execptr));
// } // }
} else { } else {
LOG("\x1b[35mExec: Add postponed word\x1b[m %s", w2->name); LOG("\x1b[35mExec: Add postponed word\x1b[m %s", w2->name);
TRY(fh_put_instr(fh, FH_INSTR_WORD, instr->data)); TRY(fh_put_instr(fh, FH_INSTR_WORD, instr->data));
} }
/*} else { /*} else {
LOGE("Postpone in interpret mode!"); LOGE("Postpone in interpret mode!");
goto end; goto end;
@ -285,20 +286,20 @@ enum fh_error w_user_word(struct fh_thread_s *fh, const struct fh_word_s *w0)
TRY(rs_peek(fh, &limit)); TRY(rs_peek(fh, &limit));
LOG("\x1b[35mExec: +LOOP\x1b[m, i=%d, step %d, limit %d", fh->loop_i, val, limit); LOG("\x1b[35mExec: +LOOP\x1b[m, i=%d, step %d, limit %d", fh->loop_i, val, limit);
const int32_t vi = (int32_t)val; const int32_t vi = (int32_t) val;
const int32_t bdr = (int32_t)limit - (int32_t)1; const int32_t bdr = (int32_t) limit - (int32_t) 1;
const int32_t i0 = (int32_t)fh->loop_i; const int32_t i0 = (int32_t) fh->loop_i;
fh->loop_i += val; // this can overflow fh->loop_i += val; // this can overflow
const int32_t i1 = (int32_t)fh->loop_i; const int32_t i1 = (int32_t) fh->loop_i;
// TODO this can probably be optimized // TODO this can probably be optimized
if ( if (
(vi > 0 && i0 <= bdr && i1 > bdr) (vi > 0 && i0 <= bdr && i1 > bdr)
|| (vi > 0 && i0 > 0 && i1 < 0 && (bdr >= i0 || bdr <= i1)) || (vi > 0 && i0 > 0 && i1 < 0 && (bdr >= i0 || bdr <= i1))
|| (vi < 0 && i0 > bdr && i1 <= bdr) || (vi < 0 && i0 > bdr && i1 <= bdr)
|| (vi < 0 && i0 < 0 && i1 > 0 && (bdr <= i0 || bdr >= i1)) || (vi < 0 && i0 < 0 && i1 > 0 && (bdr <= i0 || bdr >= i1))
) { ) {
//LOGE("end of loop"); //LOGE("end of loop");
// end of loop // end of loop
TRY(rs_pop(fh, &limit)); TRY(rs_pop(fh, &limit));
@ -329,16 +330,16 @@ enum fh_error w_user_word(struct fh_thread_s *fh, const struct fh_word_s *w0)
} }
TRY(ds_pop(fh, &testval)); TRY(ds_pop(fh, &testval));
TRY(ds_pop(fh, &val)); TRY(ds_pop(fh, &val));
LOG("Val %d, testval %d", val, testval); LOG("Val %d, testval %d", val, testval);
if (testval != val) { if (testval != val) {
LOG("No match, go to ENDOF"); LOG("No match, go to ENDOF");
TRY(ds_push(fh, val)); TRY(ds_push(fh, val));
fh->execptr = instr->data; fh->execptr = instr->data;
} }
goto instr; goto instr;
case FH_INSTR_ENDCASE: case FH_INSTR_ENDCASE:
LOG("\x1b[35mExec: ENDCASE\x1b[m"); LOG("\x1b[35mExec: ENDCASE\x1b[m");
TRY(ds_pop(fh, &val)); // discard the tested value TRY(ds_pop(fh, &val)); // discard the tested value
@ -353,11 +354,11 @@ enum fh_error w_user_word(struct fh_thread_s *fh, const struct fh_word_s *w0)
goto instr; goto instr;
case FH_INSTR_ALLOCSTR_C: case FH_INSTR_ALLOCSTR_C:
LOG("\x1b[35mExec: alloc-str-c\x1b[m \"%.*s\"", fh->heap[fh->execptr], fh_str_at(fh, fh->execptr+1)); LOG("\x1b[35mExec: alloc-str-c\x1b[m \"%.*s\"", fh->heap[fh->execptr], fh_str_at(fh, fh->execptr + 1));
TRY(ds_push(fh, fh->execptr)); TRY(ds_push(fh, fh->execptr));
fh->execptr += instr->data; fh->execptr += instr->data;
goto instr; goto instr;
case FH_INSTR_TYPESTR: case FH_INSTR_TYPESTR:
strl = instr->data; strl = instr->data;
LOG("\x1b[35mExec: type-str\x1b[m \"%.*s\"", strl, fh_str_at(fh, fh->execptr)); LOG("\x1b[35mExec: type-str\x1b[m \"%.*s\"", strl, fh_str_at(fh, fh->execptr));
@ -373,6 +374,9 @@ enum fh_error w_user_word(struct fh_thread_s *fh, const struct fh_word_s *w0)
goto end; goto end;
} }
goto instr; goto instr;
default:
LOGE("Run handler not implemented for instr opcode %d", instr->kind);
} }
end: end:
@ -401,7 +405,7 @@ enum fh_error fh_handle_word(struct fh_thread_s *fh, uint32_t addr)
{ {
enum fh_error rv; enum fh_error rv;
struct fh_word_s *w = fh_word_at(fh, addr); struct fh_word_s *w = fh_word_at(fh, addr);
if (!w) return FH_ERR_INTERNAL; if (!w) { return FH_ERR_INTERNAL; }
if (fh->state == FH_STATE_COMPILE && 0 == (w->flags & WORDFLAG_IMMEDIATE)) { if (fh->state == FH_STATE_COMPILE && 0 == (w->flags & WORDFLAG_IMMEDIATE)) {
LOG("\x1b[34m[%s] Compile word:\x1b[m %s", stateshort[fh->state], w->name); LOG("\x1b[34m[%s] Compile word:\x1b[m %s", stateshort[fh->state], w->name);
TRY(fh_put_instr(fh, FH_INSTR_WORD, addr)); TRY(fh_put_instr(fh, FH_INSTR_WORD, addr));
@ -409,7 +413,7 @@ enum fh_error fh_handle_word(struct fh_thread_s *fh, uint32_t addr)
/* interpret or immediate in compiled code */ /* interpret or immediate in compiled code */
// enum fh_state oldstate = fh->state; // enum fh_state oldstate = fh->state;
// fh_setstate(fh, FH_STATE_INTERPRET, 0); // fh_setstate(fh, FH_STATE_INTERPRET, 0);
LOG("\x1b[35m[%s] Run word:\x1b[m %s%s", stateshort[fh->state], w->name, (w->flags&WORDFLAG_IMMEDIATE)?" 'imm":""); LOG("\x1b[35m[%s] Run word:\x1b[m %s%s", stateshort[fh->state], w->name, (w->flags & WORDFLAG_IMMEDIATE) ? " 'imm" : "");
TRY(w->handler(fh, w)); TRY(w->handler(fh, w));
// if (fh->state == FH_STATE_INTERPRET && fh->substate == FH_SUBSTATE_NONE) { // if (fh->state == FH_STATE_INTERPRET && fh->substate == FH_SUBSTATE_NONE) {
// fh_setstate(fh, oldstate, 0); // fh_setstate(fh, oldstate, 0);

@ -104,13 +104,13 @@ static void show_word(struct fh_thread_s *fh, const struct fh_word_s *w)
FHPRINT("AllocStr(\"%.*s\")\n", strl, fh_str_at(fh, execptr)); FHPRINT("AllocStr(\"%.*s\")\n", strl, fh_str_at(fh, execptr));
execptr += strl; execptr += strl;
break; break;
case FH_INSTR_TYPESTR: case FH_INSTR_TYPESTR:
strl = instr->data; strl = instr->data;
FHPRINT("PrintStr(\"%.*s\")\n", strl, fh_str_at(fh, execptr)); FHPRINT("PrintStr(\"%.*s\")\n", strl, fh_str_at(fh, execptr));
execptr += strl; execptr += strl;
break; break;
case FH_INSTR_ALLOCSTR_C: case FH_INSTR_ALLOCSTR_C:
strl = instr->data; strl = instr->data;
FHPRINT("AllocStrC(%d, \"%.*s\")\n", fh->heap[execptr], fh->heap[execptr], fh_str_at(fh, execptr + 1)); FHPRINT("AllocStrC(%d, \"%.*s\")\n", fh->heap[execptr], fh->heap[execptr], fh_str_at(fh, execptr + 1));
@ -122,7 +122,7 @@ static void show_word(struct fh_thread_s *fh, const struct fh_word_s *w)
FHPRINT("END (synthetic for DOES>)\n"); FHPRINT("END (synthetic for DOES>)\n");
break; break;
} else { } else {
FHPRINT("END\n"); FHPRINT("END\n");
return; return;
} }
@ -132,7 +132,7 @@ static void show_word(struct fh_thread_s *fh, const struct fh_word_s *w)
} }
} else { } else {
FHPRINT("Built-in word %s\n", w->name); FHPRINT("Built-in word %s\n", w->name);
}; }
} else if (w->flags & WORDFLAG_VARIABLE) { } else if (w->flags & WORDFLAG_VARIABLE) {
FHPRINT("Variable %s, value %d (0x%08x)\n", w->name, (int32_t) w->param, w->param); FHPRINT("Variable %s, value %d (0x%08x)\n", w->name, (int32_t) w->param, w->param);
} else if (w->flags & WORDFLAG_CONSTANT) { } else if (w->flags & WORDFLAG_CONSTANT) {

@ -12,7 +12,7 @@ enum fh_error ds_roll(struct fh_thread_s *fh, int n)
uint32_t yn = fh->data_stack_top - 1 - n; uint32_t yn = fh->data_stack_top - 1 - n;
uint32_t yoinked = fh->data_stack[yn]; uint32_t yoinked = fh->data_stack[yn];
for (uint32_t i = yn; i < fh->data_stack_top; i++) { for (uint32_t i = yn; i < fh->data_stack_top; i++) {
fh->data_stack[i] = fh->data_stack[i+1]; fh->data_stack[i] = fh->data_stack[i + 1];
} }
fh->data_stack[fh->data_stack_top - 1] = yoinked; fh->data_stack[fh->data_stack_top - 1] = yoinked;
return FH_OK; return FH_OK;
@ -96,7 +96,7 @@ enum fh_error ds_pop_dw(struct fh_thread_s *fh, uint64_t *out)
uint32_t a, b; uint32_t a, b;
TRY(ds_pop(fh, &a)); TRY(ds_pop(fh, &a));
TRY(ds_pop(fh, &b)); TRY(ds_pop(fh, &b));
*out = ((uint64_t)a << 32) | ((uint64_t)b); *out = ((uint64_t) a << 32) | ((uint64_t) b);
return FH_OK; return FH_OK;
} }

Loading…
Cancel
Save