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