| 
						
						
							
								
							
						
						
					 | 
					 | 
					@ -7,18 +7,16 @@ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#include <stdlib.h> | 
					 | 
					 | 
					 | 
					#include <stdlib.h> | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					typedef enum { | 
					 | 
					 | 
					 | 
					typedef enum { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						PARS_COMMAND, | 
					 | 
					 | 
					 | 
						PARS_COMMAND = 0, | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// collect generic arg, terminated with comma or newline. Leading and trailing whitespace ignored.
 | 
					 | 
					 | 
					 | 
						// collect generic arg, terminated with comma or newline. Leading and trailing whitespace ignored.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						PARS_ARG, | 
					 | 
					 | 
					 | 
						PARS_ARG, // generic argument (bool, float...)
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						PARS_ARG_STR_APOS, // collect arg - string with single quotes
 | 
					 | 
					 | 
					 | 
						PARS_ARG_STRING, // collect arg - string (special treatment for quotes)
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						PARS_ARG_STR_QUOT, // collect arg - string with double quotes
 | 
					 | 
					 | 
					 | 
						PARS_ARG_BLOB_PREAMBLE, // #nDDD
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						PARS_ARG_BLOB_PREAMBLE, | 
					 | 
					 | 
					 | 
						PARS_ARG_BLOB_DISCARD, // discard blob - same as BLOB_BODY, but no callback or buffering
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						PARS_ARG_BLOB_BODY, // blob body, callback for each group
 | 
					 | 
					 | 
					 | 
						PARS_ARG_BLOB_BODY, // blob body, callback for each group
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// command with no args terminated by whitespace, discard whitespace until newline and then run callback.
 | 
					 | 
					 | 
					 | 
						PARS_TRAILING_WHITE, // command ready to run, waiting for end, only whitespace allowed
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// error on non-whitespace
 | 
					 | 
					 | 
					 | 
						PARS_TRAILING_WHITE_NOCB, // discard whitespace until end of line, don't run callback on success
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						PARS_TRAILING_WHITE, | 
					 | 
					 | 
					 | 
						PARS_DISCARD_LINE, // used after detecting error - drop all chars until \n
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						PARS_TRAILING_WHITE_NOCB, // no callback.
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						PARS_DISCARD_LINE, // used after detecting error
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} parser_state_t; | 
					 | 
					 | 
					 | 
					} parser_state_t; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#define MAX_CHARBUF_LEN 256 | 
					 | 
					 | 
					 | 
					#define MAX_CHARBUF_LEN 256 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -37,6 +35,9 @@ static struct { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						int32_t blob_cnt; // preamble counter, if 0, was just #, must read count. Used also for blob body.
 | 
					 | 
					 | 
					 | 
						int32_t blob_cnt; // preamble counter, if 0, was just #, must read count. Used also for blob body.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						int32_t blob_len; // total blob length to read
 | 
					 | 
					 | 
					 | 
						int32_t blob_len; // total blob length to read
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						char string_quote; // symbol used to quote string
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						bool string_escape; // last char was backslash, next quote is literal
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// recognized complete command level strings (FUNCtion) - exact copy from command struct
 | 
					 | 
					 | 
					 | 
						// recognized complete command level strings (FUNCtion) - exact copy from command struct
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						char cur_levels[MAX_LEVEL_COUNT][MAX_CMD_LEN]; | 
					 | 
					 | 
					 | 
						char cur_levels[MAX_LEVEL_COUNT][MAX_CMD_LEN]; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						uint8_t cur_level_i; // next free level slot index
 | 
					 | 
					 | 
					 | 
						uint8_t cur_level_i; // next free level slot index
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -47,18 +48,8 @@ static struct { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						SCPI_argval_t args[MAX_PARAM_COUNT]; | 
					 | 
					 | 
					 | 
						SCPI_argval_t args[MAX_PARAM_COUNT]; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						uint8_t arg_i; // next free argument slot index
 | 
					 | 
					 | 
					 | 
						uint8_t arg_i; // next free argument slot index
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} pst = { | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// defaults
 | 
					 | 
					 | 
					 | 
					} pst; // initialized by all zeros
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						.err_queue_i = 0, | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						.state = PARS_COMMAND, | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						.charbuf_i = 0, | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						.cur_level_i = 0, | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						.cmdbuf_kept = false, | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						.matched_cmd = NULL, | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						.blob_cnt = 0, | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						.blob_len = 0, | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						.arg_i = 0 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static void pars_cmd_colon(void); // colon starting a command sub-segment
 | 
					 | 
					 | 
					 | 
					static void pars_cmd_colon(void); // colon starting a command sub-segment
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -107,8 +98,7 @@ static void pars_reset_cmd(void) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						pst.cmdbuf_kept = false; | 
					 | 
					 | 
					 | 
						pst.cmdbuf_kept = false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						pst.matched_cmd = NULL; | 
					 | 
					 | 
					 | 
						pst.matched_cmd = NULL; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						pst.arg_i = 0; | 
					 | 
					 | 
					 | 
						pst.arg_i = 0; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						pst.blob_cnt = 0; | 
					 | 
					 | 
					 | 
						pst.string_escape = false; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						pst.blob_len = 0; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -117,18 +107,16 @@ static void pars_reset_cmd_keeplevel(void) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						pst.state = PARS_COMMAND; | 
					 | 
					 | 
					 | 
						pst.state = PARS_COMMAND; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						pst.charbuf_i = 0; | 
					 | 
					 | 
					 | 
						pst.charbuf_i = 0; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// rewind to last colon
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						// rewind to last colon
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						if (pst.cur_level_i > 0) { | 
					 | 
					 | 
					 | 
						if (pst.cur_level_i > 0) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							pst.cur_level_i--; // keep prev levels
 | 
					 | 
					 | 
					 | 
							pst.cur_level_i--; // keep prev levels
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						pst.cmdbuf_kept = true; | 
					 | 
					 | 
					 | 
						pst.cmdbuf_kept = true; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						pst.matched_cmd = NULL; | 
					 | 
					 | 
					 | 
						pst.matched_cmd = NULL; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						pst.arg_i = 0; | 
					 | 
					 | 
					 | 
						pst.arg_i = 0; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						pst.blob_cnt = 0; | 
					 | 
					 | 
					 | 
						pst.string_escape = false; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						pst.blob_len = 0; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -185,6 +173,12 @@ static void pars_run_callback(void) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					void scpi_discard_blob(void) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
						pst.state = PARS_ARG_BLOB_DISCARD; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					void scpi_handle_byte(const uint8_t b) | 
					 | 
					 | 
					 | 
					void scpi_handle_byte(const uint8_t b) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						// TODO handle blob here
 | 
					 | 
					 | 
					 | 
						// TODO handle blob here
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -277,29 +271,26 @@ void scpi_handle_byte(const uint8_t b) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								} | 
					 | 
					 | 
					 | 
								} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								break; | 
					 | 
					 | 
					 | 
								break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							// TODO escape sequence in string
 | 
					 | 
					 | 
					 | 
							case PARS_ARG_STRING: | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								// string
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							case PARS_ARG_STR_APOS: | 
					 | 
					 | 
					 | 
								if (c == pst.string_quote && !pst.string_escape) { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								if (c == '\'') { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									// end of string
 | 
					 | 
					 | 
					 | 
									// end of string
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									pst.state = PARS_ARG; // next will be newline or comma (or ignored spaces)
 | 
					 | 
					 | 
					 | 
									pst.state = PARS_ARG; // next will be newline or comma (or ignored spaces)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								} else if (c == '\n') { | 
					 | 
					 | 
					 | 
								} else if (c == '\n') { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									printf("ERROR string literal not terminated.\n");//TODO error
 | 
					 | 
					 | 
					 | 
									printf("ERROR string literal not terminated.\n");//TODO error
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									pst.state = PARS_DISCARD_LINE; | 
					 | 
					 | 
					 | 
									pst.state = PARS_DISCARD_LINE; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								} else { | 
					 | 
					 | 
					 | 
								} else { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									charbuf_append(c); | 
					 | 
					 | 
					 | 
									if (pst.string_escape) { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								} | 
					 | 
					 | 
					 | 
										charbuf_append(c); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								break; | 
					 | 
					 | 
					 | 
										pst.string_escape = false; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
									} else { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							case PARS_ARG_STR_QUOT: | 
					 | 
					 | 
					 | 
										if (c == '\\') { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								if (c == '"') { | 
					 | 
					 | 
					 | 
											pst.string_escape = true; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									// end of string
 | 
					 | 
					 | 
					 | 
										} else { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									pst.state = PARS_ARG; // next will be newline or comma (or ignored spaces)
 | 
					 | 
					 | 
					 | 
											charbuf_append(c); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								} else if (c == '\n') { | 
					 | 
					 | 
					 | 
										} | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									printf("ERROR string literal not terminated.\n");//TODO error
 | 
					 | 
					 | 
					 | 
									} | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									pst.state = PARS_DISCARD_LINE; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								} else { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									charbuf_append(c); | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								} | 
					 | 
					 | 
					 | 
								} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								break; | 
					 | 
					 | 
					 | 
								break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -309,6 +300,8 @@ void scpi_handle_byte(const uint8_t b) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								break; | 
					 | 
					 | 
					 | 
								break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							case PARS_ARG_BLOB_BODY: | 
					 | 
					 | 
					 | 
							case PARS_ARG_BLOB_BODY: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								// binary blob body with callback on buffer full
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								charbuf_append(c); | 
					 | 
					 | 
					 | 
								charbuf_append(c); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								pst.blob_cnt++; | 
					 | 
					 | 
					 | 
								pst.blob_cnt++; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -324,6 +317,17 @@ void scpi_handle_byte(const uint8_t b) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									pst.state = PARS_TRAILING_WHITE_NOCB; // discard trailing whitespace until newline
 | 
					 | 
					 | 
					 | 
									pst.state = PARS_TRAILING_WHITE_NOCB; // discard trailing whitespace until newline
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								} | 
					 | 
					 | 
					 | 
								} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							case PARS_ARG_BLOB_DISCARD: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								// binary blob, discard incoming data
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								pst.blob_cnt++; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								if (pst.blob_cnt == pst.blob_len) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									pst.state = PARS_DISCARD_LINE; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								break; | 
					 | 
					 | 
					 | 
								break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
						} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					} | 
					 | 
					 | 
					 | 
					} | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -557,27 +561,6 @@ static bool try_match_cmd(const SCPI_command_t *cmd, bool partial) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					static void pars_arg_char(char c) | 
					 | 
					 | 
					 | 
					static void pars_arg_char(char c) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					{ | 
					 | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
						switch (pst.matched_cmd->params[pst.arg_i]) { | 
					 | 
					 | 
					 | 
						switch (pst.matched_cmd->params[pst.arg_i]) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							case SCPI_DT_STRING: | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								if (c == '\'') { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									pst.state = PARS_ARG_STR_APOS; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								} else if (c == '"') { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									pst.state = PARS_ARG_STR_QUOT; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								} else { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									printf("ERROR unexpected char '%c', should be ' or \"\n", c);//TODO error
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									pst.state = PARS_DISCARD_LINE; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								} | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								break; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							case SCPI_DT_BLOB: | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								if (c == '#') { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									pst.state = PARS_ARG_BLOB_PREAMBLE; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									pst.blob_cnt = 0; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								} else { | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									printf("ERROR unexpected char '%c', binary block should start with #\n", c);//TODO error
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									pst.state = PARS_DISCARD_LINE; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								} | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								break; | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							case SCPI_DT_FLOAT: | 
					 | 
					 | 
					 | 
							case SCPI_DT_FLOAT: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								if (!IS_FLOAT_CHAR(c)) { | 
					 | 
					 | 
					 | 
								if (!IS_FLOAT_CHAR(c)) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
									printf("ERROR unexpected char '%c' in float.\n", c);//TODO error
 | 
					 | 
					 | 
					 | 
									printf("ERROR unexpected char '%c' in float.\n", c);//TODO error
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -596,6 +579,27 @@ static void pars_arg_char(char c) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								} | 
					 | 
					 | 
					 | 
								} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								break; | 
					 | 
					 | 
					 | 
								break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							case SCPI_DT_STRING: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								if (c == '\'' || c == '"') { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									pst.state = PARS_ARG_STRING; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									pst.string_quote = c; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									pst.string_escape = false; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								} else { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									printf("ERROR invalid string quote, or chars after string.\n");//TODO error
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									pst.state = PARS_DISCARD_LINE; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
							case SCPI_DT_BLOB: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								if (c == '#') { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									pst.state = PARS_ARG_BLOB_PREAMBLE; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									pst.blob_cnt = 0; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								} else { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									printf("ERROR unexpected char '%c', binary block should start with #\n", c);//TODO error
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
									pst.state = PARS_DISCARD_LINE; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
								break; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
							default: | 
					 | 
					 | 
					 | 
							default: | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								charbuf_append(c); | 
					 | 
					 | 
					 | 
								charbuf_append(c); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
								break; | 
					 | 
					 | 
					 | 
								break; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					 | 
					
  |