implement saving and restoring input, at least for string (file not tested)
This commit is contained in:
+7
-5
@@ -15,17 +15,19 @@ typedef bool (*fh_input_refill_t)(struct fh_thread_s *fh, struct fh_input_spec_s
|
||||
/** Spec free func */
|
||||
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_void_method_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);
|
||||
typedef enum fh_error (*fh_input_error_method_t)(struct fh_thread_s *fh, struct fh_input_spec_s *spec);
|
||||
|
||||
struct fh_input_spec_s {
|
||||
struct fh_input_spec_s *previous;
|
||||
fh_input_refill_t refill_input_buffer;
|
||||
fh_input_start_t start;
|
||||
fh_input_void_method_t start;
|
||||
fh_input_free_t free_self;
|
||||
fh_input_pushpop_t push_prepare;
|
||||
fh_input_pushpop_t pop_restore;
|
||||
fh_input_void_method_t push_prepare;
|
||||
fh_input_void_method_t pop_restore;
|
||||
fh_input_error_method_t save_input;
|
||||
fh_input_error_method_t restore_input;
|
||||
uint32_t linenum;
|
||||
char *cwd; // CWD of the input, used for relative includes. malloc'd (strdup)
|
||||
|
||||
|
||||
+19
-1
@@ -603,6 +603,22 @@ static enum fh_error w_evaluate(struct fh_thread_s *fh, const struct fh_word_s *
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
static enum fh_error w_save_input(struct fh_thread_s *fh, const struct fh_word_s *w)
|
||||
{
|
||||
(void) w;
|
||||
enum fh_error rv;
|
||||
fh->input->save_input(fh, fh->input);
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
static enum fh_error w_restore_input(struct fh_thread_s *fh, const struct fh_word_s *w)
|
||||
{
|
||||
(void) w;
|
||||
enum fh_error rv;
|
||||
fh->input->restore_input(fh, fh->input);
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
static enum fh_error w_included(struct fh_thread_s *fh, const struct fh_word_s *w)
|
||||
{
|
||||
(void) w;
|
||||
@@ -738,11 +754,13 @@ const struct name_and_handler fh_builtins_meta[] = {
|
||||
{"'", wp_tick, 1, 0},
|
||||
{"[']", wp_tick, 1, 1},
|
||||
{"execute", w_execute, 0, 0},
|
||||
{"save-input", w_save_input, 0, 0},
|
||||
{"restore-input",w_restore_input, 0, 0},
|
||||
{"environment?", w_env_query, 0, 0},
|
||||
{"marker", w_marker, 0, 0},
|
||||
{"compile,", w_compile_comma, 0, 0},
|
||||
{"evaluate", w_evaluate, 0, 0},
|
||||
{"included", w_included, 0, 0},
|
||||
{"include", w_include, 0, 0},
|
||||
{"include", w_include, 0, 0},
|
||||
{ /* end marker */ }
|
||||
};
|
||||
|
||||
+90
-29
@@ -1,5 +1,17 @@
|
||||
#include "forth_internal.h"
|
||||
|
||||
struct file_input_spec {
|
||||
struct fh_input_spec_s spec;
|
||||
char saved_buffer[INPUT_BUFFER_SIZE];
|
||||
FILE *file;
|
||||
};
|
||||
|
||||
struct string_input_spec {
|
||||
struct fh_input_spec_s spec;
|
||||
const char *str;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
enum fh_error fh_push_input(struct fh_thread_s *fh, struct fh_input_spec_s *newinput)
|
||||
{
|
||||
LOG("--- Push input spec ---");
|
||||
@@ -70,17 +82,78 @@ enum fh_error fh_pop_input(struct fh_thread_s *fh)
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
struct file_input_spec {
|
||||
struct fh_input_spec_s spec;
|
||||
char saved_buffer[INPUT_BUFFER_SIZE];
|
||||
FILE *file;
|
||||
};
|
||||
static enum fh_error file_save_input(struct fh_thread_s *fh, struct fh_input_spec_s *spec)
|
||||
{
|
||||
enum fh_error rv;
|
||||
struct file_input_spec *fspec = (void*) spec;
|
||||
|
||||
if (isatty(fileno(fspec->file))) {
|
||||
TRY(ds_push(fh, 0));
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
uint32_t pos = (uint32_t) ftell(fspec->file);
|
||||
|
||||
TRY(ds_push(fh, spec->linenum));
|
||||
TRY(ds_push(fh, fh->inputptr));
|
||||
TRY(ds_push(fh, pos - fh->inputlen));
|
||||
TRY(ds_push(fh, 3));
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
struct string_input_spec {
|
||||
struct fh_input_spec_s spec;
|
||||
const char *str;
|
||||
size_t len;
|
||||
};
|
||||
static enum fh_error file_restore_input(struct fh_thread_s *fh, struct fh_input_spec_s *spec)
|
||||
{
|
||||
enum fh_error rv;
|
||||
struct file_input_spec *fspec = (void*) spec;
|
||||
uint32_t n;
|
||||
TRY(ds_pop(fh, &n));
|
||||
if (n == 3) {
|
||||
uint32_t filepos;
|
||||
TRY(ds_pop(fh, &filepos));
|
||||
fseek(fspec->file, filepos, SEEK_SET);
|
||||
TRY(ds_pop(fh, &fh->inputptr));
|
||||
TRY(ds_pop(fh, &spec->linenum));
|
||||
|
||||
LOG("file input, restore filepos %d, inptr %d, linenum %d",
|
||||
filepos, fh->inputptr, spec->linenum);
|
||||
|
||||
fgets(&fh->heap[INPUTBUF_ADDR], INPUT_BUFFER_SIZE, fspec->file);
|
||||
TRY(ds_push(fh, 0));
|
||||
} else {
|
||||
LOG("file input, restore nothing, bad N!");
|
||||
TRY(ds_push(fh, TOBOOL(1)));
|
||||
}
|
||||
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
static enum fh_error str_save_input(struct fh_thread_s *fh, struct fh_input_spec_s *spec)
|
||||
{
|
||||
enum fh_error rv;
|
||||
TRY(ds_push(fh, spec->linenum));
|
||||
TRY(ds_push(fh, fh->inputptr));
|
||||
TRY(ds_push(fh, 2));
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
static enum fh_error str_restore_input(struct fh_thread_s *fh, struct fh_input_spec_s *spec)
|
||||
{
|
||||
enum fh_error rv;
|
||||
uint32_t n;
|
||||
TRY(ds_pop(fh, &n));
|
||||
if (n == 2) {
|
||||
TRY(ds_pop(fh, &fh->inputptr));
|
||||
TRY(ds_pop(fh, &spec->linenum));
|
||||
|
||||
LOG("str input, inptr %d, linenum %d",
|
||||
fh->inputptr, spec->linenum);
|
||||
TRY(ds_push(fh, 0));
|
||||
} else {
|
||||
LOG("str input, restore nothing, bad N!");
|
||||
TRY(ds_push(fh, TOBOOL(1)));
|
||||
}
|
||||
return FH_OK;
|
||||
}
|
||||
|
||||
static void file_push_prepare(struct fh_thread_s *fh, struct fh_input_spec_s *spec)
|
||||
{
|
||||
@@ -160,26 +233,8 @@ 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)
|
||||
{
|
||||
// no refilling, the string exists in its entirety on heap
|
||||
return fh->inputptr < fh->inputlen;
|
||||
// struct string_input_spec *fis = (struct string_input_spec *) spec;
|
||||
// fh_input_memmove_leftovers(fh);
|
||||
// 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) {
|
||||
// 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;
|
||||
// fis->readpos += space_left;
|
||||
// fh->inputlen += space_left;
|
||||
// return true;
|
||||
// } else {
|
||||
// return false;
|
||||
// }
|
||||
}
|
||||
|
||||
static void free_filespec(void *p)
|
||||
@@ -220,6 +275,8 @@ struct fh_input_spec_s *fh_create_input_from_filestruct(FILE *f, const char *cwd
|
||||
spec->spec.push_prepare = file_push_prepare;
|
||||
spec->spec.pop_restore = file_pop_restore;
|
||||
spec->spec.refill_input_buffer = file_refill;
|
||||
spec->spec.save_input = file_save_input;
|
||||
spec->spec.restore_input = file_restore_input;
|
||||
spec->file = f;
|
||||
if (cwd) {
|
||||
spec->spec.cwd = strdup(cwd);
|
||||
@@ -247,6 +304,8 @@ struct fh_input_spec_s *fh_create_input_from_filename(char *path)
|
||||
spec->spec.push_prepare = file_push_prepare;
|
||||
spec->spec.pop_restore = file_pop_restore;
|
||||
spec->spec.refill_input_buffer = file_refill;
|
||||
spec->spec.save_input = file_save_input;
|
||||
spec->spec.restore_input = file_restore_input;
|
||||
spec->file = f;
|
||||
|
||||
char pwd[PATH_MAX+1];
|
||||
@@ -275,6 +334,8 @@ struct fh_input_spec_s *fh_create_input_from_string(char *str, size_t len, const
|
||||
spec->spec.push_prepare = str_push_prepare;
|
||||
spec->spec.pop_restore = str_pop_restore;
|
||||
spec->spec.start = str_start;
|
||||
spec->spec.save_input = str_save_input;
|
||||
spec->spec.restore_input = str_restore_input;
|
||||
spec->str = str;
|
||||
spec->len = len;
|
||||
spec->spec.cwd = cwd ? strdup(cwd) : NULL;
|
||||
|
||||
+1
-1
@@ -386,7 +386,7 @@ enum fh_error fh_process_line(struct fh_thread_s *fh)
|
||||
}
|
||||
} else if (fh->parse_if_level == 0) {
|
||||
/* eval a word */
|
||||
LOG("Handle \"%.*s\", len %d", (int) length, rp, length);
|
||||
LOG("Handle \"%.*s\"", (int) length, rp);
|
||||
TRY(fh_handle_ascii_word(fh, rp, length));
|
||||
} else {
|
||||
if (EQ(rp, "\\", length)) {
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
\ 1 debug
|
||||
|
||||
VARIABLE SI_INC 0 SI_INC !
|
||||
|
||||
: SI1
|
||||
SI_INC @ >IN +!
|
||||
15 SI_INC !
|
||||
;
|
||||
|
||||
: S$ S" SAVE-INPUT SI1 RESTORE-INPUT 12345" ;
|
||||
|
||||
S$ EVALUATE SI_INC @
|
||||
|
||||
. . .
|
||||
|
||||
\ 0 2345 15
|
||||
|
||||
bye
|
||||
|
||||
Reference in New Issue
Block a user