#include "forth_internal.h" // extension static enum fh_error w_reset(struct fh_thread_s *fh, const struct fh_word_s *w) { (void) w; ENSURE_STATE(FH_STATE_INTERPRET); fh_init(fh); return FH_OK; } static enum fh_error w_bye(struct fh_thread_s *fh, const struct fh_word_s *w) { (void) w; fh_setstate(fh, FH_STATE_SHUTDOWN, 0); return FH_OK; } static enum fh_error w_debug(struct fh_thread_s *fh, const struct fh_word_s *w) { (void) w; enum fh_error rv; uint32_t val; TRY(ds_pop(fh, &val)); fh_globals.verbose = val; return FH_OK; } static enum fh_error w_exit(struct fh_thread_s *fh, const struct fh_word_s *w) { (void) w; enum fh_error rv; ENSURE_STATE(FH_STATE_COMPILE); // let's just hope the return stack is not clobbered! TRY(fh_put_instr(fh, FH_INSTR_ENDWORD, 0)); 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[] = { {"reset", w_reset, 1, 0}, {"bye", w_bye, 0, 0}, {"debug", w_debug, 0, 0}, {"exit", w_exit, 1, 0}, {"quit", w_quit, 0, 0}, {"abort", w_abort, 0, 0}, {"abort\"", w_abort_quote, 1, 0}, { /* end marker */ } };