implement saving and restoring input, at least for string (file not tested)

master
Ondřej Hruška 3 years ago
parent 877c98d262
commit 8d66238f47
  1. 12
      include/fh_input.h
  2. 20
      src/fh_builtins_meta.c
  3. 119
      src/fh_input.c
  4. 2
      src/fh_parse.c
  5. 19
      testfiles/saverestore.f

@ -15,17 +15,19 @@ 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_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 {
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_void_method_t start;
fh_input_free_t free_self; fh_input_free_t free_self;
fh_input_pushpop_t push_prepare; fh_input_void_method_t push_prepare;
fh_input_pushpop_t pop_restore; fh_input_void_method_t pop_restore;
fh_input_error_method_t save_input;
fh_input_error_method_t restore_input;
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)

@ -603,6 +603,22 @@ static enum fh_error w_evaluate(struct fh_thread_s *fh, const struct fh_word_s *
return FH_OK; 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) static enum fh_error w_included(struct fh_thread_s *fh, const struct fh_word_s *w)
{ {
(void) w; (void) w;
@ -738,11 +754,13 @@ const struct name_and_handler fh_builtins_meta[] = {
{"'", wp_tick, 1, 0}, {"'", wp_tick, 1, 0},
{"[']", wp_tick, 1, 1}, {"[']", wp_tick, 1, 1},
{"execute", w_execute, 0, 0}, {"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}, {"environment?", w_env_query, 0, 0},
{"marker", w_marker, 0, 0}, {"marker", w_marker, 0, 0},
{"compile,", w_compile_comma, 0, 0}, {"compile,", w_compile_comma, 0, 0},
{"evaluate", w_evaluate, 0, 0}, {"evaluate", w_evaluate, 0, 0},
{"included", w_included, 0, 0}, {"included", w_included, 0, 0},
{"include", w_include, 0, 0}, {"include", w_include, 0, 0},
{ /* end marker */ } { /* end marker */ }
}; };

@ -1,5 +1,17 @@
#include "forth_internal.h" #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) enum fh_error fh_push_input(struct fh_thread_s *fh, struct fh_input_spec_s *newinput)
{ {
LOG("--- Push input spec ---"); LOG("--- Push input spec ---");
@ -70,17 +82,78 @@ enum fh_error fh_pop_input(struct fh_thread_s *fh)
return FH_OK; return FH_OK;
} }
struct file_input_spec { static enum fh_error file_save_input(struct fh_thread_s *fh, struct fh_input_spec_s *spec)
struct fh_input_spec_s spec; {
char saved_buffer[INPUT_BUFFER_SIZE]; enum fh_error rv;
FILE *file; struct file_input_spec *fspec = (void*) spec;
};
struct string_input_spec { if (isatty(fileno(fspec->file))) {
struct fh_input_spec_s spec; TRY(ds_push(fh, 0));
const char *str; return FH_OK;
size_t len; }
};
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;
}
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) 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) 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; 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) 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.push_prepare = file_push_prepare;
spec->spec.pop_restore = file_pop_restore; spec->spec.pop_restore = file_pop_restore;
spec->spec.refill_input_buffer = file_refill; spec->spec.refill_input_buffer = file_refill;
spec->spec.save_input = file_save_input;
spec->spec.restore_input = file_restore_input;
spec->file = f; spec->file = f;
if (cwd) { if (cwd) {
spec->spec.cwd = strdup(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.push_prepare = file_push_prepare;
spec->spec.pop_restore = file_pop_restore; spec->spec.pop_restore = file_pop_restore;
spec->spec.refill_input_buffer = file_refill; spec->spec.refill_input_buffer = file_refill;
spec->spec.save_input = file_save_input;
spec->spec.restore_input = file_restore_input;
spec->file = f; spec->file = f;
char pwd[PATH_MAX+1]; 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.push_prepare = str_push_prepare;
spec->spec.pop_restore = str_pop_restore; spec->spec.pop_restore = str_pop_restore;
spec->spec.start = str_start; spec->spec.start = str_start;
spec->spec.save_input = str_save_input;
spec->spec.restore_input = str_restore_input;
spec->str = str; spec->str = str;
spec->len = len; spec->len = len;
spec->spec.cwd = cwd ? strdup(cwd) : NULL; spec->spec.cwd = cwd ? strdup(cwd) : NULL;

@ -386,7 +386,7 @@ enum fh_error fh_process_line(struct fh_thread_s *fh)
} }
} else if (fh->parse_if_level == 0) { } else if (fh->parse_if_level == 0) {
/* eval a word */ /* 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)); TRY(fh_handle_ascii_word(fh, rp, length));
} else { } else {
if (EQ(rp, "\\", length)) { 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
Loading…
Cancel
Save