diff --git a/include/fh_mem.h b/include/fh_mem.h index e7e5506..f636e98 100644 --- a/include/fh_mem.h +++ b/include/fh_mem.h @@ -7,6 +7,8 @@ #ifndef FORTH_FH_MEM_H #define FORTH_FH_MEM_H +void fh_fill_input_buffer(struct fh_thread_s *fh, const char *data, size_t num); + void fh_align(struct fh_thread_s *fh); void fh_setbase(struct fh_thread_s *fh, uint32_t base); diff --git a/include/fh_runtime.h b/include/fh_runtime.h index f80d893..ab5ee6a 100644 --- a/include/fh_runtime.h +++ b/include/fh_runtime.h @@ -148,6 +148,11 @@ struct fh_thread_s { /** Address of the last dict word */ uint32_t dict_last; + /** Input buffer parse position */ + uint32_t inputptr; + /** Input buffer total content size */ + uint32_t inputlen; + /** Forth state */ enum fh_state state; @@ -158,6 +163,10 @@ struct fh_thread_s { uint32_t base; }; +#define HEAP_END (HEAP_SIZE - WORDBUF_SIZE - INPUT_BUFFER_SIZE) +#define WORDBUF_ADDR HEAP_END +#define INPUTBUF_ADDR (HEAP_END + WORDBUF_SIZE) + enum fh_error fh_add_word(const struct fh_word_s *w, struct fh_thread_s *fh); void fh_setstate(struct fh_thread_s *fh, enum fh_state state, enum fh_substate substate); diff --git a/include/forth.h b/include/forth.h index cd3af4b..dc64cc8 100644 --- a/include/forth.h +++ b/include/forth.h @@ -16,6 +16,6 @@ struct fh_thread_s; enum fh_error fh_init(struct fh_thread_s *fh); -enum fh_error fh_process_line(struct fh_thread_s *fh, const char *linebuf); +enum fh_error fh_process_line(struct fh_thread_s *fh, const char *linebuf, size_t len); #endif //FORTH_H diff --git a/src/fh_builtins.c b/src/fh_builtins.c index 88ec39d..bf7bcaf 100644 --- a/src/fh_builtins.c +++ b/src/fh_builtins.c @@ -992,7 +992,7 @@ static enum fh_error w_pad(struct fh_thread_s *fh, const struct fh_word_s *w) (void) w; enum fh_error rv; uint32_t addr = fh->here + PAD_OFFSET; - if (addr + 84 >= HEAP_SIZE) { + if (addr + 84 >= HEAP_END) { LOGE("Heap overflow, PAD is too small!"); return FH_ERR_HEAP_FULL; } diff --git a/src/fh_mem.c b/src/fh_mem.c index 7cd0777..1a7818e 100644 --- a/src/fh_mem.c +++ b/src/fh_mem.c @@ -1,10 +1,23 @@ #include +#include #include "fh_print.h" #include "fh_error.h" #include "fh_runtime.h" #include "fh_mem.h" +// Important distinction: HEAP_END is the end of the normally addressable region. HEAP_SIZE is the full memory area. +// Buffers are placed at the end of the heap! + +void fh_fill_input_buffer(struct fh_thread_s *fh, const char *data, size_t num) +{ + assert(num <= INPUT_BUFFER_SIZE); + memcpy(&fh->heap[INPUTBUF_ADDR], data, num); + fh->heap[INPUTBUF_ADDR+num] = 0; // terminator + fh->inputptr = 0; + fh->inputlen = num; +} + void fh_align(struct fh_thread_s *fh) { fh->here = WORDALIGNED(fh->here); @@ -102,7 +115,7 @@ enum fh_error fh_heap_reserve( { uint32_t p = fh->here; - if (p + len > HEAP_SIZE) { + if (p + len > HEAP_END) { return FH_ERR_HEAP_FULL; } @@ -121,6 +134,11 @@ enum fh_error fh_heap_reserve( /** Write bytes to heap at a given location. The region must have been previously allocated! */ void fh_heap_write(struct fh_thread_s *fh, uint32_t addr, const void *src, uint32_t len) { + if (addr > HEAP_SIZE) { + LOGE("Attempted write past end of heap"); + return; + } + memcpy(&fh->heap[addr], src, len); } @@ -149,14 +167,14 @@ 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) { - if (addr >= HEAP_SIZE) { + if (addr >= HEAP_END) { LOGE("fh_instr_at out of bounds!"); } return (void *) &fh->heap[addr]; } struct fh_word_s *fh_word_at(struct fh_thread_s *fh, uint32_t addr) { - if (addr >= HEAP_SIZE) { + if (addr >= HEAP_END) { LOGE("fh_word_at out of bounds!"); } return (struct fh_word_s *) &fh->heap[addr]; diff --git a/src/fh_runtime.c b/src/fh_runtime.c index c090523..31a9237 100644 --- a/src/fh_runtime.c +++ b/src/fh_runtime.c @@ -233,6 +233,7 @@ static enum fh_error fh_handle_quoted_string( if (fh->state == FH_STATE_INTERPRET) { switch (fh->substate) { case FH_SUBSTATE_S_QUOTE: + addr = fh->here; TRY(fh_heap_put(fh, start, len)); TRY(ds_push(fh, addr)); TRY(ds_push(fh, len)); @@ -461,27 +462,36 @@ static inline bool isnl(char c) } /** Process a line read from input */ -enum fh_error fh_process_line(struct fh_thread_s *fh, const char *linebuf) +enum fh_error fh_process_line(struct fh_thread_s *fh, const char *linebuf, size_t len) { enum fh_error rv; - const char *rp = linebuf; + +#define ReadPtr ((char*)(&fh->heap[INPUTBUF_ADDR + fh->inputptr])) +#define ReadPos (fh->inputptr) +#define ReadLen (fh->inputlen) + + fh_fill_input_buffer(fh, linebuf, len); + char c; if (!fh_globals.interactive) { LOGI("%s", linebuf); } - while (0 != (c = *rp) && fh->state != FH_STATE_SHUTDOWN) { + while (ReadPos < ReadLen && fh->state != FH_STATE_SHUTDOWN) { + c = *ReadPtr; /* end on newline */ if (isnl(c)) { goto done; } /* skip whitespace */ if (isspace(c)) { - rp++; + ReadPos++; continue; } + const char * const rp = ReadPtr; + char *end; size_t length; switch (fh->substate) { @@ -520,7 +530,7 @@ enum fh_error fh_process_line(struct fh_thread_s *fh, const char *linebuf) } if (end) { - rp = end + 1; + ReadPos += length + 1; } else { goto done; } @@ -534,7 +544,7 @@ enum fh_error fh_process_line(struct fh_thread_s *fh, const char *linebuf) LOG("Quoted string: \"%.*s\"", (int) length, rp); TRY(fh_handle_quoted_string(fh, rp, length)); fh_setsubstate(fh, FH_SUBSTATE_NONE); - rp = end + 1; + ReadPos += length + 1; } else { /* no end. this is weird. */ LOGE("Unterminated quoted string!"); @@ -545,9 +555,10 @@ enum fh_error fh_process_line(struct fh_thread_s *fh, const char *linebuf) case FH_SUBSTATE_PAREN_COMMENT: end = strchr(rp, ')'); if (end) { + length = end - rp; LOG("Discard inline comment"); fh_setsubstate(fh, FH_SUBSTATE_NONE); - rp = end + 1; + ReadPos += length + 1; } else { /* no end, discard all */ LOGE("Unterminated parenthesis comment"); diff --git a/src/main.c b/src/main.c index f8bd195..d411b72 100644 --- a/src/main.c +++ b/src/main.c @@ -68,7 +68,7 @@ int main(int argc, char *argv[]) continue; } - rv = fh_process_line(&fh, linebuf); + rv = fh_process_line(&fh, linebuf, strlen(linebuf)); if (rv == FH_OK) { FHPRINT_SVC(" ok\n"); } else {