|
|
@ -37,11 +37,76 @@ static enum fh_error w_exit(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
return FH_OK; |
|
|
|
return FH_OK; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static enum fh_error w_abort(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
(void) w; |
|
|
|
|
|
|
|
enum fh_error rv; |
|
|
|
|
|
|
|
fh_abort(fh); |
|
|
|
|
|
|
|
return FH_OK; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static enum fh_error w_quit(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
(void) w; |
|
|
|
|
|
|
|
enum fh_error rv; |
|
|
|
|
|
|
|
fh_quit(fh); |
|
|
|
|
|
|
|
return FH_OK; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static enum fh_error w_abort_quote(struct fh_thread_s *fh, const struct fh_word_s *w) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
(void) w; |
|
|
|
|
|
|
|
enum fh_error rv; |
|
|
|
|
|
|
|
size_t len; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// this is copied from ."
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// leave space for the instr in case of compiled version
|
|
|
|
|
|
|
|
uint32_t addr = fh->here + (fh->state == FH_STATE_INTERPRET ? 0 : INSTR_SIZE); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* read the string straight into HEAP, but don't advance the heap pointer, so the string is immediately discarded again */ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fh_input_consume_spaces(fh); |
|
|
|
|
|
|
|
char *start; |
|
|
|
|
|
|
|
uint32_t capacity = HEAP_END - addr; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
start = NULL; |
|
|
|
|
|
|
|
char c = '"'; |
|
|
|
|
|
|
|
TRY(fh_input_read_delimited(fh, &start, &len, fh_chartest_equals_or_end, &c)); |
|
|
|
|
|
|
|
if (len > capacity) { |
|
|
|
|
|
|
|
LOGE("String too long for heap"); |
|
|
|
|
|
|
|
return FH_ERR_HEAP_FULL; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (fh->state == FH_STATE_COMPILE) { |
|
|
|
|
|
|
|
fh_heap_copyptr(fh, addr, start, len); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (fh->state == FH_STATE_INTERPRET) { |
|
|
|
|
|
|
|
uint32_t val; |
|
|
|
|
|
|
|
TRY(ds_pop(fh, &val)); |
|
|
|
|
|
|
|
if (val) { |
|
|
|
|
|
|
|
FHPRINT("%.*s", (int) len, start);
|
|
|
|
|
|
|
|
fh_abort(fh); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// the string is invalidated immediately, heap pointer is NOT advanced.
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
LOG("Compile abort string: \"%.*s\"", (int) len, start); |
|
|
|
|
|
|
|
TRY(fh_put_instr(fh, FH_INSTR_ABORTSTR, len)); |
|
|
|
|
|
|
|
fh->here = WORDALIGNED(addr + len); // at the end of the string
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return FH_OK; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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}, |
|
|
|
|
|
|
|
{"quit", w_quit, 0, 0}, |
|
|
|
|
|
|
|
{"abort", w_abort, 0, 0}, |
|
|
|
|
|
|
|
{"abort\"", w_abort_quote, 1, 0}, |
|
|
|
|
|
|
|
|
|
|
|
{ /* end marker */ } |
|
|
|
{ /* end marker */ } |
|
|
|
}; |
|
|
|
}; |
|
|
|