|
|
|
@ -1,38 +1,39 @@ |
|
|
|
|
#include "forth_internal.h" |
|
|
|
|
|
|
|
|
|
void 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 ---"); |
|
|
|
|
|
|
|
|
|
if (newinput == NULL) { |
|
|
|
|
LOGE("push input with NULL"); |
|
|
|
|
return; |
|
|
|
|
return FH_ERR_INTERNAL; // TODO IO
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct fh_input_spec_s *oldinput = fh->input; |
|
|
|
|
if (NULL == oldinput) { |
|
|
|
|
// no previous input spec, just use the new one
|
|
|
|
|
fh->input = newinput; |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fh->input = NULL; |
|
|
|
|
|
|
|
|
|
memcpy(&oldinput->saved_buffer[0], &fh->heap[INPUTBUF_ADDR], INPUT_BUFFER_SIZE); |
|
|
|
|
oldinput->saved_inputlen = fh->inputlen; |
|
|
|
|
oldinput->saved_inputptr = fh->inputptr; |
|
|
|
|
// oldinput->saved_state = fh->state;
|
|
|
|
|
oldinput->saved_execptr = fh->execptr; |
|
|
|
|
newinput->previous = oldinput; |
|
|
|
|
if (NULL != oldinput) { |
|
|
|
|
memcpy(&oldinput->saved_buffer[0], &fh->heap[INPUTBUF_ADDR], INPUT_BUFFER_SIZE); |
|
|
|
|
oldinput->saved_inputlen = fh->inputlen; |
|
|
|
|
oldinput->saved_inputptr = fh->inputptr; |
|
|
|
|
oldinput->saved_execptr = fh->execptr; |
|
|
|
|
newinput->previous = oldinput; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fh->inputlen = 0; |
|
|
|
|
fh->inputptr = 0; |
|
|
|
|
|
|
|
|
|
// fh_setstate(fh, FH_STATE_INTERPRET, 0);
|
|
|
|
|
fh->input = newinput; |
|
|
|
|
|
|
|
|
|
if (newinput->cwd) { |
|
|
|
|
LOG("CD to %s", newinput->cwd); |
|
|
|
|
chdir(newinput->cwd); |
|
|
|
|
} |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void fh_pop_input(struct fh_thread_s *fh) |
|
|
|
|
enum fh_error fh_pop_input(struct fh_thread_s *fh) |
|
|
|
|
{ |
|
|
|
|
LOG("--- Pop input spec ---"); |
|
|
|
|
|
|
|
|
@ -41,7 +42,7 @@ void fh_pop_input(struct fh_thread_s *fh) |
|
|
|
|
|
|
|
|
|
struct fh_input_spec_s *restored = discarded->previous; |
|
|
|
|
if (!restored) { |
|
|
|
|
return; |
|
|
|
|
return FH_OK; // topmost
|
|
|
|
|
} |
|
|
|
|
fh->input = restored; // this can be NULL, that must be checked by caller.
|
|
|
|
|
|
|
|
|
@ -54,6 +55,12 @@ void fh_pop_input(struct fh_thread_s *fh) |
|
|
|
|
if (discarded->free_self) { |
|
|
|
|
discarded->free_self(discarded); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (restored->cwd) { |
|
|
|
|
LOG("CD to %s", restored->cwd); |
|
|
|
|
chdir(restored->cwd); |
|
|
|
|
} |
|
|
|
|
return FH_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct file_input_spec { |
|
|
|
@ -63,7 +70,7 @@ struct file_input_spec { |
|
|
|
|
|
|
|
|
|
struct string_input_spec { |
|
|
|
|
struct fh_input_spec_s spec; |
|
|
|
|
char *str; |
|
|
|
|
const char *str; |
|
|
|
|
size_t len; |
|
|
|
|
size_t readpos; |
|
|
|
|
}; |
|
|
|
@ -137,36 +144,56 @@ static bool str_refill(struct fh_thread_s *fh, struct fh_input_spec_s *spec) |
|
|
|
|
|
|
|
|
|
static void free_filespec(void *p) |
|
|
|
|
{ |
|
|
|
|
struct file_input_spec *spec = (struct file_input_spec *) p; |
|
|
|
|
if (spec->file != stdin) { |
|
|
|
|
fclose(spec->file); |
|
|
|
|
spec->file = NULL; |
|
|
|
|
struct file_input_spec *fis = (struct file_input_spec *) p; |
|
|
|
|
if (fis->file != stdin) { |
|
|
|
|
fclose(fis->file); |
|
|
|
|
fis->file = NULL; |
|
|
|
|
} |
|
|
|
|
if (fis->spec.cwd) { |
|
|
|
|
free(fis->spec.cwd); |
|
|
|
|
fis->spec.cwd = NULL; |
|
|
|
|
} |
|
|
|
|
free(spec); |
|
|
|
|
free(fis); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct fh_input_spec_s *fh_create_input_from_filestruct(FILE *f) |
|
|
|
|
static void free_strspec(void *p) |
|
|
|
|
{ |
|
|
|
|
struct file_input_spec *spec = calloc(sizeof(struct file_input_spec), 1); |
|
|
|
|
if (!spec) { |
|
|
|
|
struct string_input_spec *sis = (struct string_input_spec *) p; |
|
|
|
|
if (sis->spec.cwd) { |
|
|
|
|
free(sis->spec.cwd); |
|
|
|
|
sis->spec.cwd = NULL; |
|
|
|
|
} |
|
|
|
|
free(sis); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
if (!fis) { |
|
|
|
|
LOGE("Err alloc input spec struct"); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
spec->spec.free_self = free; |
|
|
|
|
spec->spec.refill_input_buffer = file_refill; |
|
|
|
|
spec->file = f; |
|
|
|
|
return (struct fh_input_spec_s*) spec; |
|
|
|
|
fis->spec.free_self = free_filespec; |
|
|
|
|
fis->spec.refill_input_buffer = file_refill; |
|
|
|
|
fis->file = f; |
|
|
|
|
if (cwd) { |
|
|
|
|
fis->spec.cwd = strdup(cwd); |
|
|
|
|
} |
|
|
|
|
return (struct fh_input_spec_s*) fis; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct fh_input_spec_s *fh_create_input_from_filename(char *path) |
|
|
|
|
{ |
|
|
|
|
struct file_input_spec *spec = calloc(sizeof(struct file_input_spec), 1); |
|
|
|
|
if (!spec) { |
|
|
|
|
LOGE("Err alloc input spec struct"); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
FILE *f = fopen(path, "r"); |
|
|
|
|
if (!f) { |
|
|
|
|
LOGE("Err open file \"%s\"", path); |
|
|
|
|
free(spec); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
@ -174,22 +201,33 @@ struct fh_input_spec_s *fh_create_input_from_filename(char *path) |
|
|
|
|
spec->spec.free_self = free_filespec; |
|
|
|
|
spec->spec.refill_input_buffer = file_refill; |
|
|
|
|
spec->file = f; |
|
|
|
|
|
|
|
|
|
char pwd[PATH_MAX+1]; |
|
|
|
|
realpath(path, pwd); |
|
|
|
|
char *end = strrchr(pwd, '/'); |
|
|
|
|
if (end) { |
|
|
|
|
// add terminator
|
|
|
|
|
*end = 0; |
|
|
|
|
} |
|
|
|
|
spec->spec.cwd = strdup(pwd); |
|
|
|
|
LOG("Input for file %s, path %s\n", path, pwd); |
|
|
|
|
return (struct fh_input_spec_s*) spec; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct fh_input_spec_s *fh_create_input_from_string(char *str, size_t len) |
|
|
|
|
struct fh_input_spec_s *fh_create_input_from_string(char *str, size_t len, const char *cwd) |
|
|
|
|
{ |
|
|
|
|
struct string_input_spec *spec = calloc(sizeof(struct string_input_spec), 1); |
|
|
|
|
if (!spec) { |
|
|
|
|
struct string_input_spec *sis = calloc(sizeof(struct string_input_spec), 1); |
|
|
|
|
if (!sis) { |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
spec->spec.free_self = free; |
|
|
|
|
spec->spec.refill_input_buffer = str_refill; |
|
|
|
|
spec->str = str; |
|
|
|
|
spec->readpos = 0; |
|
|
|
|
spec->len = len; |
|
|
|
|
return (struct fh_input_spec_s*) spec; |
|
|
|
|
sis->spec.free_self = free_strspec; |
|
|
|
|
sis->spec.refill_input_buffer = str_refill; |
|
|
|
|
sis->str = str; |
|
|
|
|
sis->readpos = 0; |
|
|
|
|
sis->len = len; |
|
|
|
|
sis->spec.cwd = cwd ? strdup(cwd) : NULL; |
|
|
|
|
return (struct fh_input_spec_s*) sis; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void fh_input_teardown(struct fh_thread_s *fh) |
|
|
|
|