|  |  |  | @ -37,11 +37,76 @@ static enum fh_error w_exit(struct fh_thread_s *fh, const struct fh_word_s *w) | 
			
		
	
		
			
				
					|  |  |  |  |   return FH_OK; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static enum fh_error w_abort(struct fh_thread_s *fh, const struct fh_word_s *w) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |   (void) w; | 
			
		
	
		
			
				
					|  |  |  |  |   enum fh_error rv; | 
			
		
	
		
			
				
					|  |  |  |  |   fh_abort(fh); | 
			
		
	
		
			
				
					|  |  |  |  |   return FH_OK; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static enum fh_error w_quit(struct fh_thread_s *fh, const struct fh_word_s *w) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |   (void) w; | 
			
		
	
		
			
				
					|  |  |  |  |   enum fh_error rv; | 
			
		
	
		
			
				
					|  |  |  |  |   fh_quit(fh); | 
			
		
	
		
			
				
					|  |  |  |  |   return FH_OK; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | static enum fh_error w_abort_quote(struct fh_thread_s *fh, const struct fh_word_s *w) | 
			
		
	
		
			
				
					|  |  |  |  | { | 
			
		
	
		
			
				
					|  |  |  |  |   (void) w; | 
			
		
	
		
			
				
					|  |  |  |  |   enum fh_error rv; | 
			
		
	
		
			
				
					|  |  |  |  |   size_t len; | 
			
		
	
		
			
				
					|  |  |  |  |   
 | 
			
		
	
		
			
				
					|  |  |  |  |   // this is copied from ."
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   // leave space for the instr in case of compiled version
 | 
			
		
	
		
			
				
					|  |  |  |  |   uint32_t addr = fh->here + (fh->state == FH_STATE_INTERPRET ? 0 : INSTR_SIZE); | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   /* read the string straight into HEAP, but don't advance the heap pointer, so the string is immediately discarded again */ | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   fh_input_consume_spaces(fh); | 
			
		
	
		
			
				
					|  |  |  |  |   char *start; | 
			
		
	
		
			
				
					|  |  |  |  |   uint32_t capacity = HEAP_END - addr; | 
			
		
	
		
			
				
					|  |  |  |  |   
 | 
			
		
	
		
			
				
					|  |  |  |  |   start = NULL; | 
			
		
	
		
			
				
					|  |  |  |  |   char c = '"'; | 
			
		
	
		
			
				
					|  |  |  |  |   TRY(fh_input_read_delimited(fh, &start, &len, fh_chartest_equals_or_end, &c)); | 
			
		
	
		
			
				
					|  |  |  |  |   if (len > capacity) { | 
			
		
	
		
			
				
					|  |  |  |  |     LOGE("String too long for heap"); | 
			
		
	
		
			
				
					|  |  |  |  |     return FH_ERR_HEAP_FULL; | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  |   if (fh->state == FH_STATE_COMPILE) { | 
			
		
	
		
			
				
					|  |  |  |  |     fh_heap_copyptr(fh, addr, start, len); | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   if (fh->state == FH_STATE_INTERPRET) { | 
			
		
	
		
			
				
					|  |  |  |  |     uint32_t val; | 
			
		
	
		
			
				
					|  |  |  |  |     TRY(ds_pop(fh, &val)); | 
			
		
	
		
			
				
					|  |  |  |  |     if (val) { | 
			
		
	
		
			
				
					|  |  |  |  |       FHPRINT("%.*s", (int) len, start);      
 | 
			
		
	
		
			
				
					|  |  |  |  |       fh_abort(fh); | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  |     // the string is invalidated immediately, heap pointer is NOT advanced.
 | 
			
		
	
		
			
				
					|  |  |  |  |   } else { | 
			
		
	
		
			
				
					|  |  |  |  |     LOG("Compile abort string: \"%.*s\"", (int) len, start); | 
			
		
	
		
			
				
					|  |  |  |  |     TRY(fh_put_instr(fh, FH_INSTR_ABORTSTR, len)); | 
			
		
	
		
			
				
					|  |  |  |  |     fh->here = WORDALIGNED(addr + len); // at the end of the string
 | 
			
		
	
		
			
				
					|  |  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |   return FH_OK; | 
			
		
	
		
			
				
					|  |  |  |  | } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | const struct name_and_handler fh_builtins_system[] = { | 
			
		
	
		
			
				
					|  |  |  |  |     {"reset", w_reset, 1, 0}, | 
			
		
	
		
			
				
					|  |  |  |  |     {"bye",   w_bye,   0, 0}, | 
			
		
	
		
			
				
					|  |  |  |  |     {"debug", w_debug, 0, 0}, | 
			
		
	
		
			
				
					|  |  |  |  |     {"exit",  w_exit,  1, 0}, | 
			
		
	
		
			
				
					|  |  |  |  |     {"quit",   w_quit,   0, 0}, | 
			
		
	
		
			
				
					|  |  |  |  |     {"abort",   w_abort,   0, 0}, | 
			
		
	
		
			
				
					|  |  |  |  |     {"abort\"", w_abort_quote, 1, 0}, | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     { /* end marker */ } | 
			
		
	
		
			
				
					|  |  |  |  | }; | 
			
		
	
	
		
			
				
					|  |  |  | 
 |