|
|
@ -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) |
|
|
|