Compare commits

..

3 Commits

  1. 9
      include/fh_input.h
  2. 2
      include/fh_runtime.h
  3. 5
      src/fh_builtins_meta.c
  4. 139
      src/fh_input.c
  5. 9
      src/fh_mem.c
  6. 23
      src/fh_parse.c
  7. 3
      testfiles/combinedtest.f
  8. 7
      testfiles/rescan.f

@ -15,15 +15,22 @@ typedef bool (*fh_input_refill_t)(struct fh_thread_s *fh, struct fh_input_spec_s
/** Spec free func */ /** Spec free func */
typedef void (*fh_input_free_t)(void *spec); typedef void (*fh_input_free_t)(void *spec);
typedef void (*fh_input_start_t)(struct fh_thread_s *fh, struct fh_input_spec_s *spec);
typedef void (*fh_input_pushpop_t)(struct fh_thread_s *fh, struct fh_input_spec_s *spec);
struct fh_input_spec_s { struct fh_input_spec_s {
struct fh_input_spec_s *previous; struct fh_input_spec_s *previous;
fh_input_refill_t refill_input_buffer; fh_input_refill_t refill_input_buffer;
fh_input_start_t start;
fh_input_free_t free_self; fh_input_free_t free_self;
fh_input_pushpop_t push_prepare;
fh_input_pushpop_t pop_restore;
uint32_t linenum; uint32_t linenum;
char *cwd; // CWD of the input, used for relative includes. malloc'd (strdup) char *cwd; // CWD of the input, used for relative includes. malloc'd (strdup)
// saved values, filled when pushing // saved values, filled when pushing
char saved_buffer[INPUT_BUFFER_SIZE]; uint32_t saved_inputaddr;
uint32_t saved_inputptr; uint32_t saved_inputptr;
uint32_t saved_inputlen; uint32_t saved_inputlen;
uint32_t saved_execptr; uint32_t saved_execptr;

@ -193,6 +193,8 @@ struct fh_thread_s {
/** Pictured numeric output buffer write cursor (used for prepend) */ /** Pictured numeric output buffer write cursor (used for prepend) */
uint32_t pictnumptr; uint32_t pictnumptr;
/** Start addr of the input string (SOURCE) */
uint32_t inputaddr;
/** Input buffer parse position */ /** Input buffer parse position */
uint32_t inputptr; uint32_t inputptr;
/** Input buffer total content size */ /** Input buffer total content size */

@ -295,10 +295,8 @@ static enum fh_error w_source(struct fh_thread_s *fh, const struct fh_word_s *w)
{ {
(void) w; (void) w;
enum fh_error rv; enum fh_error rv;
TRY(ds_push(fh, INPUTBUF_ADDR)); TRY(ds_push(fh, fh->inputaddr));
TRY(ds_push(fh, fh->inputlen)); TRY(ds_push(fh, fh->inputlen));
// TRY(ds_push(fh, INPUTBUF_ADDR + fh->inputptr));
// TRY(ds_push(fh, fh->inputlen - fh->inputptr));
return FH_OK; return FH_OK;
} }
@ -601,7 +599,6 @@ static enum fh_error w_evaluate(struct fh_thread_s *fh, const struct fh_word_s *
enum fh_error rv; enum fh_error rv;
uint32_t addr, count; uint32_t addr, count;
TRY(ds_pop_addr_len(fh, &addr, &count)); TRY(ds_pop_addr_len(fh, &addr, &count));
fh_runtime_start(fh, fh_create_input_from_string(fh_str_at(fh, addr), count, fh->input->cwd)); fh_runtime_start(fh, fh_create_input_from_string(fh_str_at(fh, addr), count, fh->input->cwd));
return FH_OK; return FH_OK;
} }

@ -13,13 +13,17 @@ enum fh_error fh_push_input(struct fh_thread_s *fh, struct fh_input_spec_s *newi
fh->input = NULL; fh->input = NULL;
if (NULL != oldinput) { if (NULL != oldinput) {
memcpy(&oldinput->saved_buffer[0], &fh->heap[INPUTBUF_ADDR], INPUT_BUFFER_SIZE); oldinput->push_prepare(fh, oldinput);
// memcpy(&oldinput->saved_buffer[0], &fh->heap[INPUTBUF_ADDR], INPUT_BUFFER_SIZE);
oldinput->saved_inputlen = fh->inputlen; oldinput->saved_inputlen = fh->inputlen;
oldinput->saved_inputptr = fh->inputptr; oldinput->saved_inputptr = fh->inputptr;
oldinput->saved_execptr = fh->execptr; oldinput->saved_execptr = fh->execptr;
oldinput->saved_inputaddr = fh->inputaddr;
newinput->previous = oldinput; newinput->previous = oldinput;
} }
fh->execptr = MAGICADDR_EXEC_INTERACTIVE;
fh->inputlen = 0; fh->inputlen = 0;
fh->inputptr = 0; fh->inputptr = 0;
@ -46,10 +50,13 @@ enum fh_error fh_pop_input(struct fh_thread_s *fh)
} }
fh->input = restored; // this can be NULL, that must be checked by caller. fh->input = restored; // this can be NULL, that must be checked by caller.
memcpy(&fh->heap[INPUTBUF_ADDR], &restored->saved_buffer[0], INPUT_BUFFER_SIZE); restored->pop_restore(fh, restored);
// memcpy(&fh->heap[INPUTBUF_ADDR], &restored->saved_buffer[0], INPUT_BUFFER_SIZE);
fh->inputlen = restored->saved_inputlen; fh->inputlen = restored->saved_inputlen;
fh->inputptr = restored->saved_inputptr; fh->inputptr = restored->saved_inputptr;
fh->execptr = restored->saved_execptr; fh->execptr = restored->saved_execptr;
fh->inputaddr = restored->saved_inputaddr;
// fh_setstate(fh, restored->saved_state, 0); // fh_setstate(fh, restored->saved_state, 0);
if (discarded->free_self) { if (discarded->free_self) {
@ -65,6 +72,7 @@ enum fh_error fh_pop_input(struct fh_thread_s *fh)
struct file_input_spec { struct file_input_spec {
struct fh_input_spec_s spec; struct fh_input_spec_s spec;
char saved_buffer[INPUT_BUFFER_SIZE];
FILE *file; FILE *file;
}; };
@ -72,12 +80,31 @@ struct string_input_spec {
struct fh_input_spec_s spec; struct fh_input_spec_s spec;
const char *str; const char *str;
size_t len; size_t len;
size_t readpos;
}; };
static void file_push_prepare(struct fh_thread_s *fh, struct fh_input_spec_s *spec)
{
struct file_input_spec *fspec = (void*) spec;
memcpy(&fspec->saved_buffer[0], &fh->heap[INPUTBUF_ADDR], INPUT_BUFFER_SIZE);
}
static void file_pop_restore(struct fh_thread_s *fh, struct fh_input_spec_s *spec)
{
struct file_input_spec *fspec = (void*) spec;
memcpy(&fh->heap[INPUTBUF_ADDR], &fspec->saved_buffer[0], INPUT_BUFFER_SIZE);
}
static void str_push_prepare(struct fh_thread_s *fh, struct fh_input_spec_s *spec)
{
}
static void str_pop_restore(struct fh_thread_s *fh, struct fh_input_spec_s *spec)
{
}
static inline uint8_t *inputbuf_at(struct fh_thread_s *fh, size_t pos) static inline uint8_t *inputbuf_at(struct fh_thread_s *fh, size_t pos)
{ {
return &fh->heap[INPUTBUF_ADDR + pos]; return &fh->heap[fh->inputaddr + pos];
} }
void fh_input_memmove_leftovers(struct fh_thread_s *fh) void fh_input_memmove_leftovers(struct fh_thread_s *fh)
@ -86,33 +113,45 @@ void fh_input_memmove_leftovers(struct fh_thread_s *fh)
// something is left // something is left
uint32_t remains = fh->inputlen - fh->inputptr; uint32_t remains = fh->inputlen - fh->inputptr;
if (remains > 0) { if (remains > 0) {
LOG("Refill, reuse %d bytes left in buffer", remains);
memmove(inputbuf_at(fh, 0), inputbuf_at(fh, fh->inputptr), remains); memmove(inputbuf_at(fh, 0), inputbuf_at(fh, fh->inputptr), remains);
fh->inputptr = 0; fh->inputptr = 0;
fh->inputlen = remains; fh->inputlen = remains;
} else { } else {
LOG("Refill, nothing reused (1)");
fh->inputptr = 0; fh->inputptr = 0;
fh->inputlen = 0; fh->inputlen = 0;
} }
} else { } else {
LOG("Refill, nothing reused (2)");
fh->inputptr = 0; fh->inputptr = 0;
fh->inputlen = 0; fh->inputlen = 0;
} }
} }
static void file_start(struct fh_thread_s *fh, struct fh_input_spec_s *spec)
{
fh->inputaddr = INPUTBUF_ADDR;
//
}
static void str_start(struct fh_thread_s *fh, struct fh_input_spec_s *spec)
{
struct string_input_spec *strspec = (struct string_input_spec *) spec;
fh->inputaddr = (void*)strspec->str - (void*)&fh->heap[0]; // XXX this will explode if string is not in the internal heap!
fh->inputlen = strspec->len;
fh->inputptr = 0;
}
static bool file_refill(struct fh_thread_s *fh, struct fh_input_spec_s *spec) static bool file_refill(struct fh_thread_s *fh, struct fh_input_spec_s *spec)
{ {
struct file_input_spec *fis = (struct file_input_spec *) spec; struct file_input_spec *fis = (struct file_input_spec *) spec;
fh_input_memmove_leftovers(fh); fh_input_memmove_leftovers(fh);
uint32_t space_left = INPUT_BUFFER_SIZE - fh->inputlen - 1; uint32_t space_left = INPUT_BUFFER_SIZE - fh->inputlen - 1;
char *wp = (char *) inputbuf_at(fh, fh->inputptr); char *wp = (char *) inputbuf_at(fh, fh->inputptr);
LOG("spec %p, fgets %d", spec, space_left); //LOG("spec %p, fgets %d", spec, space_left);
if (fgets(wp, (int) space_left, fis->file)) { if (fgets(wp, (int) space_left, fis->file)) {
spec->linenum++; spec->linenum++;
fh->inputlen = strnlen(wp, INPUT_BUFFER_SIZE); fh->inputlen = strnlen(wp, INPUT_BUFFER_SIZE);
LOG("read %d bytes from file", fh->inputlen); wp[fh->inputlen] = 0;
//LOG("read %d bytes from file", fh->inputlen);
return true; return true;
} else { } else {
return fh->inputptr > fh->inputlen; // return false only if there is nothing left return fh->inputptr > fh->inputlen; // return false only if there is nothing left
@ -121,25 +160,26 @@ static bool file_refill(struct fh_thread_s *fh, struct fh_input_spec_s *spec)
static bool str_refill(struct fh_thread_s *fh, struct fh_input_spec_s *spec) static bool str_refill(struct fh_thread_s *fh, struct fh_input_spec_s *spec)
{ {
struct string_input_spec *fis = (struct string_input_spec *) spec; return fh->inputptr < fh->inputlen;
fh_input_memmove_leftovers(fh); // struct string_input_spec *fis = (struct string_input_spec *) spec;
uint32_t space_left = INPUT_BUFFER_SIZE - fh->inputlen - 1; // fh_input_memmove_leftovers(fh);
char *wp = (char *) inputbuf_at(fh, fh->inputptr); // uint32_t space_left = INPUT_BUFFER_SIZE - fh->inputlen - 1;
// char *wp = (char *) inputbuf_at(fh, fh->inputptr);
uint32_t chars_remaining_in_string = fis->len - fis->readpos; //
if (chars_remaining_in_string > 0) { // uint32_t chars_remaining_in_string = fis->len - fis->readpos;
if (chars_remaining_in_string < space_left) { // if (chars_remaining_in_string > 0) {
space_left = chars_remaining_in_string; // if (chars_remaining_in_string < space_left) {
} // space_left = chars_remaining_in_string;
// }
memcpy(wp, &fis->str[fis->readpos], space_left); //
*(wp + space_left) = 0; // memcpy(wp, &fis->str[fis->readpos], space_left);
fis->readpos += space_left; // *(wp + space_left) = 0;
fh->inputlen += space_left; // fis->readpos += space_left;
return true; // fh->inputlen += space_left;
} else { // return true;
return false; // } else {
} // return false;
// }
} }
static void free_filespec(void *p) static void free_filespec(void *p)
@ -168,19 +208,23 @@ static void free_strspec(void *p)
struct fh_input_spec_s *fh_create_input_from_filestruct(FILE *f, const char *cwd) struct fh_input_spec_s *fh_create_input_from_filestruct(FILE *f, const char *cwd)
{ {
struct file_input_spec *fis = calloc(sizeof(struct file_input_spec), 1); struct file_input_spec *spec = calloc(sizeof(struct file_input_spec), 1);
if (!fis) { if (!spec) {
LOGE("Err alloc input spec struct"); LOGE("Err alloc input spec struct");
return NULL; return NULL;
} }
fis->spec.free_self = free_filespec; LOG("Input for FILE, cwd: %s", cwd);
fis->spec.refill_input_buffer = file_refill; spec->spec.free_self = free_filespec;
fis->file = f; spec->spec.start = file_start;
spec->spec.push_prepare = file_push_prepare;
spec->spec.pop_restore = file_pop_restore;
spec->spec.refill_input_buffer = file_refill;
spec->file = f;
if (cwd) { if (cwd) {
fis->spec.cwd = strdup(cwd); spec->spec.cwd = strdup(cwd);
} }
return (struct fh_input_spec_s*) fis; return (struct fh_input_spec_s*) spec;
} }
struct fh_input_spec_s *fh_create_input_from_filename(char *path) struct fh_input_spec_s *fh_create_input_from_filename(char *path)
@ -199,6 +243,9 @@ struct fh_input_spec_s *fh_create_input_from_filename(char *path)
} }
spec->spec.free_self = free_filespec; spec->spec.free_self = free_filespec;
spec->spec.start = file_start;
spec->spec.push_prepare = file_push_prepare;
spec->spec.pop_restore = file_pop_restore;
spec->spec.refill_input_buffer = file_refill; spec->spec.refill_input_buffer = file_refill;
spec->file = f; spec->file = f;
@ -216,18 +263,22 @@ struct fh_input_spec_s *fh_create_input_from_filename(char *path)
struct fh_input_spec_s *fh_create_input_from_string(char *str, size_t len, const char *cwd) struct fh_input_spec_s *fh_create_input_from_string(char *str, size_t len, const char *cwd)
{ {
struct string_input_spec *sis = calloc(sizeof(struct string_input_spec), 1); struct string_input_spec *spec = calloc(sizeof(struct string_input_spec), 1);
if (!sis) { if (!spec) {
return NULL; return NULL;
} }
sis->spec.free_self = free_strspec; LOG("Evaluating: \"%.*s\"", (int)len, str);
sis->spec.refill_input_buffer = str_refill;
sis->str = str; spec->spec.free_self = free_strspec;
sis->readpos = 0; spec->spec.refill_input_buffer = str_refill;
sis->len = len; spec->spec.push_prepare = str_push_prepare;
sis->spec.cwd = cwd ? strdup(cwd) : NULL; spec->spec.pop_restore = str_pop_restore;
return (struct fh_input_spec_s*) sis; spec->spec.start = str_start;
spec->str = str;
spec->len = len;
spec->spec.cwd = cwd ? strdup(cwd) : NULL;
return (struct fh_input_spec_s*) spec;
} }
void fh_input_teardown(struct fh_thread_s *fh) void fh_input_teardown(struct fh_thread_s *fh)

@ -3,15 +3,6 @@
// Important distinction: HEAP_END is the end of the normally addressable region. HEAP_SIZE is the full memory area. // 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! // 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) void fh_align(struct fh_thread_s *fh)
{ {
fh->here = WORDALIGNED(fh->here); fh->here = WORDALIGNED(fh->here);

@ -63,7 +63,7 @@ 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[fh->inputaddr + fh->inputptr];
while (test(*rp, param)) { while (test(*rp, param)) {
rp++; rp++;
fh->inputptr++; fh->inputptr++;
@ -72,7 +72,7 @@ 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[fh->inputaddr + fh->inputptr];
while (isspace(*rp)) { while (isspace(*rp)) {
rp++; rp++;
fh->inputptr++; fh->inputptr++;
@ -81,9 +81,9 @@ 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[fh->inputaddr + fh->inputptr];
char *start = rp; char *start = rp;
while (1) { while (fh->inputptr < fh->inputlen) {
char c = *rp; char c = *rp;
if (test(c, param)) { if (test(c, param)) {
if (rp == start) { if (rp == start) {
@ -98,6 +98,9 @@ enum fh_error fh_input_read_delimited(struct fh_thread_s *fh, char **out, size_t
rp++; rp++;
fh->inputptr++; fh->inputptr++;
} }
*out = start;
*len = rp - start;
return FH_OK;
} }
static bool chartest_space_or_end(char c, void *param) static bool chartest_space_or_end(char c, void *param)
@ -113,7 +116,7 @@ enum fh_error fh_input_read_word(struct fh_thread_s *fh, char **out, size_t *len
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[fh->inputaddr + fh->inputptr];
bool next_escaped = false; bool next_escaped = false;
size_t remains = capacity; size_t remains = capacity;
size_t len = 0; size_t len = 0;
@ -233,12 +236,14 @@ enum fh_error fh_runtime_start(struct fh_thread_s *fh, struct fh_input_spec_s *i
FHPRINT("%s", FH_PROMPT_STR); FHPRINT("%s", FH_PROMPT_STR);
} }
input->start(fh, input);
while (1) { while (1) {
LOG("Refill input buffer"); //LOG("Refill input buffer");
if (fh->input->refill_input_buffer(fh, fh->input)) { if (fh->input->refill_input_buffer(fh, fh->input)) {
// discard spaces at the end // discard spaces at the end
while (isspace(fh->heap[INPUTBUF_ADDR + fh->inputlen - 1]) && fh->inputlen > 0) { while (isspace(fh->heap[fh->inputaddr + fh->inputlen - 1]) && fh->inputlen > 0) {
fh->heap[INPUTBUF_ADDR + fh->inputlen - 1] = 0; fh->heap[fh->inputaddr + fh->inputlen - 1] = 0;
fh->inputlen--; fh->inputlen--;
} }
@ -291,7 +296,7 @@ enum fh_error fh_process_line(struct fh_thread_s *fh)
{ {
enum fh_error rv; enum fh_error rv;
#define ReadPtr ((char*)(&fh->heap[INPUTBUF_ADDR + fh->inputptr])) #define ReadPtr ((char*)(&fh->heap[fh->inputaddr + fh->inputptr]))
#define ReadPos (fh->inputptr) #define ReadPos (fh->inputptr)
#define ReadLen (fh->inputlen) #define ReadLen (fh->inputlen)

@ -1049,6 +1049,7 @@ TESTING OUTPUT: . ." CR EMIT SPACE SPACES TYPE U.
T{ OUTPUT-TEST -> }T T{ OUTPUT-TEST -> }T
0 [if]
\ ------------------------------------------------------------------------ \ ------------------------------------------------------------------------
TESTING INPUT: ACCEPT TESTING INPUT: ACCEPT
@ -1062,6 +1063,7 @@ CREATE ABUF 50 CHARS ALLOT
; ;
T{ ACCEPT-TEST -> }T T{ ACCEPT-TEST -> }T
[then]
\ ------------------------------------------------------------------------ \ ------------------------------------------------------------------------
TESTING DICTIONARY SEARCH RULES TESTING DICTIONARY SEARCH RULES
@ -1586,6 +1588,7 @@ T{ 25 RN2 EXECUTE -> 33 22 11 0 }T
\ ----------------------------------------------------------------------------- \ -----------------------------------------------------------------------------
TESTING C" TESTING C"
1 debug
T{ : CQ1 C" 123" ; -> }T T{ : CQ1 C" 123" ; -> }T
T{ CQ1 COUNT EVALUATE -> 123 }T T{ CQ1 COUNT EVALUATE -> 123 }T
T{ : CQ2 C" " ; -> }T T{ : CQ2 C" " ; -> }T

@ -0,0 +1,7 @@
VARIABLE SCANS
: RESCAN? -1 SCANS +! SCANS @ IF 0 >IN ! THEN ;
1 debug
: GS2 1 SCANS ! S" 123 RESCAN?" EVALUATE ;
GS2
??
Loading…
Cancel
Save