/* START LIBRARY DESCRIPTION *********************************************
PARSER.LIB
	Copyright (c) 1997, Avtech Electrosystems Ltd.

DESCRIPTION:
	Parser functions.

SUPPORT LIB'S:
END DESCRIPTION **********************************************************/


#include "error_utils.h"
#include "parser.h"
#include "flash.h"
#include "nicutils.h"
#include "version.h"
#include "i2c.h"
#include "lcd.h"
#include "menus.h"
#include "gpib.h"

#include <glib/gprintf.h>

extern void send_message(gchar* message);

//STATICS
static int query_int (gchar** response, int n);
static int query_min_max_float (gchar** response, char *parameter, float min_val, float max_val);
static int query_min_max_int (gchar** response, char *parameter, int min_val, int max_val);
static int query_string (gchar** response, char *in);
static int query_float (gchar** response, float value);

static int process_float_param (char *parameter, float *value, float min_val, float max_val, int zero_mode);
static int process_int_param (char *parameter, int *value, int item_count, int *valid_nums, int allow_on_off);
static int process_int_range (char *parameter, int *value, int min_val, int max_val);
static int process_on_off (char *parameter, int *value);
static int process_two_ints (char *parameter, int *value, int min, int max);

static int check_channel_ok (int channel, int enabled_channels, char chankey);
static int Parser_id_word(char *id_me, int *channel, int *with_id_code);
static int Parser_find_commands(int commands[], int command_depth);
static gchar* filter_input (gchar *raw_in);
static int Parser_get_unit(char **parameter, char **units);
static int Parser_channel (int *channel,int with_id_code,int routine_num);
static int Handle_Units(float *mult,char *units, char *base);
static int Is_Min_Command(char *text);
static int Is_Max_Command(char *text);

static int Go_syst_err_11(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_syst_errcnt66(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_Str_eprom_47(gchar** response, int channel, char *loc_string,char *store_string,int command_type);
static int Go_int_eprom_48(gchar** response, int channel, char *loc_string,char *store_string,int command_type);
static int Go_Float_eprom51(gchar** response, int channel, char *loc_string,char *store_string,int command_type);
static int Go_char_eprom_70(gchar** response, int channel, char *loc_string,char *store_string,int command_type);
static int Go_eprom_siz_86(gchar** response, int channel, int command_type);
static int Go_sys_net_91(gchar** response, int channel, char *parameter,char *units,int command_type);

static int Go_ampl_26(gchar** response, int channel, char *parameter,char *units,int command_type,char *mode);
static int Go_pw_36(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_duty_37(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_offset_29(gchar** response, int channel, char *parameter,char *units,int command_type,char *mode);
static int Go_idn_5(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_freq_32_33(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_period_35(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_delay_39(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_dbl_pulse_40(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_func_34(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_polarity_42(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_hold_38(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_output_55(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_trig_source46(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_gate_type_56(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_gate_level_67(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_delay_test58(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_wai_10(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_opc_5(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_ese_2(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_esr_3(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_cls_1(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_sre_7(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_stb_8(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_tst_9(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_syst_ver_12(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_event_13(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_oper_enable15(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_ques_enable18(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_preset_19(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_zout_20(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_prot_trip_21(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_gpib_addr_59(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_ser_baud_60(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_ser_rts_64(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_load_68(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_meas_ampl_69(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_rst_6(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_calib_amp_72(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_calib_mon_73(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_mon_step_74(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_outputtype_75(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_calib_os_76(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_calib_pw_77(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_routeclose_78(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Parse_chan_list(int channel,char *parameter,int *primary_selected, int *secondary_selected,gchar** response);
static int Go_dly_shift_82(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_amp_pnt_83(gchar** response, int channel, char *parameter,char *units,int command_type,int cal_type);
static int Go_puls_count_88(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_puls_sep_89(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_sys_pwd_92(gchar** response, int channel, char *parameter,int command_type);
static int Go_eprom_sus_93(gchar** response, int channel, char *parameter,int command_type);
static int Go_rise_time_94(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_rcl_53(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_sav_54(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_soft_current_limit_96(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_curr_slew_98(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_cal_100(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_cal_interval_101(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_eprom_reset_102(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_atten_103(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_eprom_resize_105(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_eprom_resize_ampl_106(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_eprom_resize_offset_107(gchar** response, int channel, char *parameter,char *units,int command_type);
static int Go_cal_checking_disable_108(gchar** response, int channel, char *parameter,char *units,int command_type);


static int Parser_id_word(char *id_me, int *channel, int *with_id_code)
{
	int id_code;
	int set_new_channel;

	set_new_channel=0;

	/* detect channel suffixes in the range of 0-99 */
	if (isdigit((int) id_me[strlen(id_me)-1])) {
		set_new_channel=1;
		*channel=atoi(id_me+strlen(id_me)-1);
		if (isdigit((int) id_me[strlen(id_me)-2])) {
			*channel=atoi(id_me+strlen(id_me)-2);
			id_me[strlen(id_me)-2]=0;
		} else {
			id_me[strlen(id_me)-1]=0;
		}
	}


	if (!strcmp(id_me,"") ) {
		id_code = 0;
	} else if (!strcmp(id_me,"*cls") ) {
		id_code = 1;
	} else if (!strcmp(id_me,"*ese") ) {
		id_code = 2;
	} else if (!strcmp(id_me,"*esr") ) {
		id_code = 4;
	} else if (!strcmp(id_me,"*idn") ) {
		id_code = 5;
	} else if (!strcmp(id_me,"*opc") ) {
		id_code = 6;
	} else if (!strcmp(id_me,"*rst") ) {
		id_code = 8;
	} else if (!strcmp(id_me,"*sre") ) {
		id_code = 9;
	} else if (!strcmp(id_me,"*stb") ) {
		id_code = 10;
	} else if (!strcmp(id_me,"*tst") ) {
		id_code = 11;
	} else if (!strcmp(id_me,"*wai") ) {
		id_code = 12;
	} else if (!strcmp(id_me,"system") || !strcmp(id_me,"syst")) {
		id_code = 13;
	} else if (!strcmp(id_me,"error") || !strcmp(id_me,"err"))	{
		id_code = 14;
	} else if (!strcmp(id_me,"version") || !strcmp(id_me,"vers")) {
		id_code = 15;
	} else if (!strcmp(id_me,"status") || !strcmp(id_me,"stat") || !strcmp(id_me,"state")) {
		id_code = 16;
	} else if (!strcmp(id_me,"operation") || !strcmp(id_me,"oper")) {
		id_code = 17;
	} else if (!strcmp(id_me,"event") || !strcmp(id_me,"even")) {
		id_code = 18;
	} else if (!strcmp(id_me,"condition") || !strcmp(id_me,"cond")) {
		id_code = 19;
	} else if (!strcmp(id_me,"enable") || !strcmp(id_me,"enab")) {
		id_code = 20;
	} else if (!strcmp(id_me,"questionable") || !strcmp(id_me,"ques")) {
		id_code = 21;
	} else if (!strcmp(id_me,"preset") || !strcmp(id_me,"pres")) {
		id_code = 22;
	} else if (!strcmp(id_me,"diagnostic") || !strcmp(id_me,"diag")) {
		id_code = 23;
	} else if (!strcmp(id_me,"output") || !strcmp(id_me,"outp")) {
		id_code = 24;
	} else if (!strcmp(id_me,"impedance") || !strcmp(id_me,"imp"))	{
		id_code = 25;
	} else if (!strcmp(id_me,"protection") || !strcmp(id_me,"prot")) {
		id_code = 26;
	} else if (!strcmp(id_me,"tripped") || !strcmp(id_me,"trip")) {
		id_code = 27;
	} else if (!strcmp(id_me,"source") || !strcmp(id_me,"sour")) {
		id_code = 28;
	} else if (!strcmp(id_me,"current") || !strcmp(id_me,"curr")) {
		id_code = 29;
	} else if (!strcmp(id_me,"level") || !strcmp(id_me,"lev"))	{
		id_code = 30;
	} else if (!strcmp(id_me,"immediate") || !strcmp(id_me,"imm"))	{
		id_code = 31;
	} else if (!strcmp(id_me,"amplitude") || !strcmp(id_me,"ampl")) {
		id_code = 32;
	} else if (!strcmp(id_me,"offset") || !strcmp(id_me,"offs")) {
		id_code = 33;
	} else if (!strcmp(id_me,"high") ) {
		id_code = 34;
	} else if (!strcmp(id_me,"low") ) {
		id_code = 35;
	} else if (!strcmp(id_me,"voltage") || !strcmp(id_me,"volt")) {
		id_code = 36;
	} else if (!strcmp(id_me,"frequency") || !strcmp(id_me,"freq")) {
		id_code = 37;
	} else if (!strcmp(id_me,"function") || !strcmp(id_me,"func")) {
		id_code = 38;
	} else if (!strcmp(id_me,"shape") || !strcmp(id_me,"shap")) {
		id_code = 39;
	} else if (!strcmp(id_me,"pulse") || !strcmp(id_me,"puls")) {
		id_code = 40;
	} else if (!strcmp(id_me,"period") || !strcmp(id_me,"per"))	{
		id_code = 41;
	} else if (!strcmp(id_me,"width") || !strcmp(id_me,"widt")) {
		id_code = 42;
	} else if (!strcmp(id_me,"dcycle") || !strcmp(id_me,"dcyc")) {
		id_code = 43;
	} else if (!strcmp(id_me,"hold") ) {
		id_code = 44;
	} else if (!strcmp(id_me,"delay") || !strcmp(id_me,"del"))	{
		id_code = 45;
	} else if (!strcmp(id_me,"double") || !strcmp(id_me,"doub")) {
		id_code = 46;
	} else if (!strcmp(id_me,"polarity") || !strcmp(id_me,"pol"))	{
		id_code = 47;
	} else if (!strcmp(id_me,"beeper") || !strcmp(id_me,"beep")) {
		id_code = 48;
	} else if (!strcmp(id_me,"cw") )	{
		id_code = 49;
	} else if (!strcmp(id_me,"fixed") || !strcmp(id_me,"fix"))	{
		id_code = 50;
	} else if (!strcmp(id_me,"abort") || !strcmp(id_me,"abor")) {
		id_code = 51;
	} else if (!strcmp(id_me,"initiate") || !strcmp(id_me,"init")) {
		id_code = 52;
	} else if (!strcmp(id_me,"continuous")) {
		id_code = 53;
	} else if (!strcmp(id_me,"trigger") || !strcmp(id_me,"trig")) {
		id_code = 54;
	} else if (!strcmp(id_me,"integer") || !strcmp(id_me,"int"))	{
		id_code = 55;
	} else if (!strcmp(id_me,"float") )	{
		id_code = 56;
	} else if (!strcmp(id_me,"eprom") ) {
		id_code = 57;
	} else if (!strcmp(id_me,"string") ) {
		id_code = 58;
	} else if (!strcmp(id_me,"bit") ) {
		id_code = 59;
	} else if (!strcmp(id_me,"set") ) {
		id_code = 60;
	} else if (!strcmp(id_me,"clear") )	{
		id_code = 61;
	} else if (!strcmp(id_me,"shiftreg") )	{
		id_code = 62;
	} else if (!strcmp(id_me,"*rcl") ) {
		id_code = 63;
	} else if (!strcmp(id_me,"*sav") ) {
		id_code = 64;
	} else if (!strcmp(id_me,"gate") ) {
		id_code = 65;
	} else if (!strcmp(id_me,"local") || !strcmp(id_me,"logout") || !strcmp(id_me,"exit") || !strcmp(id_me,"quit") )	{
		id_code = 66;
	} else if (!strcmp(id_me,"test") ) {
		id_code = 67;
	} else if (!strcmp(id_me,"communicate") || !strcmp(id_me,"comm")) {
		id_code = 68;
	} else if (!strcmp(id_me,"address") || !strcmp(id_me,"addr")) {
		id_code = 69;
	} else if (!strcmp(id_me,"gpib") ) {
		id_code = 70;
	} else if (!strcmp(id_me,"serial") || !strcmp(id_me,"ser")) {
		id_code = 71;
	} else if (!strcmp(id_me,"receive") || !strcmp(id_me,"rec")) {
		id_code = 72;
	} else if (!strcmp(id_me,"baud") ) {
		id_code = 73;
	} else if (!strcmp(id_me,"parity") || !strcmp(id_me,"par")) {
		id_code = 74;
	} else if (!strcmp(id_me,"type") ) {
		id_code = 75;
	} else if (!strcmp(id_me,"bits") ) {
		id_code = 76;
	} else if (!strcmp(id_me,"sbits") || !strcmp(id_me,"sbit")) {
		id_code = 77;
	} else if (!strcmp(id_me,"echo") ) {
		id_code = 78;
	} else if (!strcmp(id_me,"rts") ) {
		id_code = 79;
	} else if (!strcmp(id_me,"control") || !strcmp(id_me,"cont"))	{
		id_code = 80;
	} else if (!strcmp(id_me,"next") ) {
		id_code = 81;
	} else if (!strcmp(id_me,"count") || !strcmp(id_me,"coun"))	{
		id_code = 82;
	} else if (!strcmp(id_me,"display") || !strcmp(id_me,"disp"))	{
		id_code = 83;
	} else if (!strcmp(id_me,"brightness") || !strcmp(id_me,"brig"))	{
		id_code = 84;
	} else if (!strcmp(id_me,"load") ) {
		id_code = 85;
	} else if (!strcmp(id_me,"measure") || !strcmp(id_me,"meas"))	{
		id_code = 86;
	} else if (!strcmp(id_me,"char") ) {
		id_code = 87;
	} else if (!strcmp(id_me,"calibration") || !strcmp(id_me,"cal"))	{
		id_code = 88;
	} else if (!strcmp(id_me,"monitor") || !strcmp(id_me,"mon"))	{
		id_code = 89;
	} else if (!strcmp(id_me,"step") ) {
		id_code = 90;
	} else if (!strcmp(id_me,"route") || !strcmp(id_me,"rout")) {
		id_code = 91;
	} else if (!strcmp(id_me,"close") || !strcmp(id_me,"clos")) {
		id_code = 92;
	} else if (!strcmp(id_me,"point") ) {
		id_code = 93;
	} else if (!strcmp(id_me,"shift") ) {
		id_code = 94;
	} else if (!strcmp(id_me,"scale") ) {
		id_code = 95;
	} else if (!strcmp(id_me,"null") ) {
		id_code = 96;
	} else if (!strcmp(id_me,"size") ) {
		id_code = 97;
	} else if (!strcmp(id_me,"separation") || !strcmp(id_me,"sep"))	{
		id_code = 98;
	} else if (!strcmp(id_me,"network") || !strcmp(id_me,"net"))	{
		id_code = 99;
	} else if (!strcmp(id_me,"password") || !strcmp(id_me,"pass"))	{
		id_code = 100;
	} else if (!strcmp(id_me,"new") ) {
		id_code = 101;
	} else if (!strcmp(id_me,"suspend") ) {
		id_code = 102;
	} else if (!strcmp(id_me,"transition") || !strcmp(id_me,"tran"))	{
		id_code = 103;
	} else if (!strcmp(id_me,"leading") || !strcmp(id_me,"lead"))	{
		id_code = 104;
	} else if (!strcmp(id_me,"limit") || !strcmp(id_me,"lim"))	{
		id_code = 105;
	} else if (!strcmp(id_me,"slew") )	{
		id_code = 106;
	} else if (!strcmp(id_me,"all") ) {
		id_code = 107;
	} else if (!strcmp(id_me,"reset") || !strcmp(id_me,"res"))      {
		id_code = 108;
	} else if (!strcmp(id_me,"attenuator") || !strcmp(id_me,"att"))      {
		id_code = 109;
	} else if (!strcmp(id_me,"distort")) {
		id_code = 110;
	} else if (!strcmp(id_me,"resize")) {
		id_code = 111;
	} else if (!strcmp(id_me,"check")) {
                id_code = 112;
        } else if (!strcmp(id_me,"disable")) {
                id_code = 113;
	} else {
		id_code = 9999;
	}

	if (set_new_channel) {
		*with_id_code=id_code;
	}

	return id_code;

}

static int Parser_find_commands(int commands[], int command_depth)
{
#define optional  16384 /* set bit high if optional */
#define opt_mask 16383  /* default bit mask */
#define max_tokens_in_sentence 7
#define max_no_of_sentences 110

	/* Valid command -sequences-. The -individual- commands are defined in id_word. */

	static const int sentences[max_no_of_sentences][max_tokens_in_sentence] =	{
		{0},	/* null - error */
		{1},	/* cls - sentence 1 */
		{2},	/* ese - sentence 2 */
		{4},	/* esr - sentence 3 */
		{5},	/* idn - sentence 4 */
		{6},	/* opc - sentence 5 */
		{8},	/* rst - sentence 6 */
		{9},	/* sre - sentence 7 */
		{10},	/* stb - sentence 8 */
		{11},	/* tst - sentence 9 */
		{12},	/* wai - sentence 10 */
		{13,14,81|optional},	/* syst:err:next - 11 */
		{13,15},		/* syst:vers - 12 */
		{16,17,18|optional},	/* stat:oper:event - 13 */
		{16,17,19},		/* stat:oper:cond - 14 */
		{16,17,20},		/* stat:oper:enable - 15 */
		{16,21,18|optional},	/* stat:ques:event - 16 */
		{16,21,19},		/* stat:ques:cond - 17 */
		{16,21,20},		/* stat:ques:enable - 18 */
		{16,22},		/* stat:preset - 19 */
		{24,25},		/* output:impedance - 20 */
		{24,26,27},		/* output:prot:tripped - 21 */
		{28|optional,29,30|optional,31|optional,32|optional},	/* sour:curr:lev:imm:ampl - 22 */
		{28|optional,29,30|optional,31|optional,33},		/* sour:curr:lev:imm:offset - 23 - not used */
		{28|optional,29,30|optional,31|optional,34},		/* sour:curr:lev:imm:high - 24 - not used */
		{28|optional,29,30|optional,31|optional,35},		/* sour:curr:lev:imm:low - 25 */
		{28|optional,36,30|optional,31|optional,32|optional},	/* sour:volt:lev:imm:ampl - 26 */
		{28|optional,36,30|optional,31|optional,33},		/* sour:volt:lev:imm:offset - 27 - not used */
		{28|optional,36,30|optional,31|optional,34},	/* sour:volt:lev:imm:high - 28 - not used */
		{28|optional,36,30|optional,31|optional,35},	/* sour:volt:lev:imm:low - 29 */
		{28|optional,29,26,27},		/* sour:curr:prot:tripped? - 30 */
		{28|optional,36,26,27},		/* sour:volt:prot:tripped? - 31 */
		{28|optional,37,49|optional},	/* sour:freq:cw - 32 */
		{28|optional,37,50|optional},	/* sour:freq:fixed - 33 */
		{28|optional,38,39|optional},	/* sour:func:shape - 34 */
		{28|optional,40,41},		/* sour:puls:per - 35 */
		{28|optional,40,42},		/* sour:puls:width - 36 */
		{28|optional,40,43},		/* sour:puls:dcyc - 37 */
		{28|optional,40,44},		/* sour:puls:hold - 38 */
		{28|optional,40,45},		/* sour:puls:delay - 39 */
		{28|optional,40,46,16|optional},	/* sour:puls:doub:state - 40 */
		{28|optional,40,46,45},			/* sour:puls:doub:delay - 41 */
		{28|optional,40,47},			/* sour:puls:pol - 42 */
		{13,48,31|optional},	/* syst:beep:imm - 43 - not used */
		{52,31|optional,53},	/* init:imm:cont - 44 - not used */
		{51},			/* abort - 45 - not used */
		{54,31|optional,28},	/* trig:imm:sour - 46 */
		{23,57,58},		/* diag:eprom:string - 47 */
		{23,57,55},		/* diag:eprom:int - 48 */
		{23,57,59,60},		/* diag:eprom:bit:set - 49 - not used */
		{23,57,59,61},		/* diag:eprom:bit:clear - 50 - not used */
		{23,57,56},		/* diag:eprom:float - 51 */
		{23,62},		/* diag:shiftreg - 52 */
		{63},			/* *rcl - 53 */
		{64},			/* *sav - 54 */
		{24,16|optional},	/* output:state - 55 */
		{28|optional,40,65,75},	/* sour:puls:gate:type - 56 */
		{66},			/* local (RS232 mode only) - 57 */
		{23,67,45},		/* diag:test:delay - 58 */
		{13,68,70,69},			/* syst:comm:gpib:addr - 59 */
		{13,68,71,72|optional,73},	/* syst:comm:ser:rec:baud - 60 */
		{13,68,71,72|optional,74,75|optional},	/* syst:comm:ser:rec:parity - 61 - not used */
		{13,68,71,72|optional,76},	/* syst:comm:ser:rec:bits - 62 - not used */
		{13,68,71,72|optional,77},	/* syst:comm:ser:rec:sbits - 63 - not used */
		{13,68,71,80,79},		/* syst:comm:ser:control:rts - 64 */
		{13,68,71,72|optional,78},	/* syst:comm:ser:rec:echo - 65 - not used */
		{13,14,82},	  		/* syst:err:count - 66 */
		{28|optional,40,65,30},		/* sour:puls:gate:level - 67 */
		{24,85},			/* output:load - 68 */
		{86,32},			/* meas:ampl? - 69 */
		{23,57,87},			/* diag:eprom:char - 70 */
		{23,88},			/* diag:calib - 71 */
		{23,32,88,95|optional}, 	/* diag:ampl:calib:scale - 72 */
		{23,89,88,95|optional}, 	/* diag:mon:calib:scale - 73 */
		{23,89,90},			/* diag:mon:step - 74 */
		{24,75},			/* output:type - 75 */
		{23,33,88,95|optional}, 	/* diag:offset:calib:scale - 76 */
		{23,40,42,88,94},		/* diag:pulse:width:calib:shift - 77 */
		{91,92},			/* route:close - 78 */
		{23,40,42,88,93},		/* diag:pulse:width:calib:point - 79 */
		{23,40,45,88,93},		/* diag:pulse:delay:calib:point - 80 */
		{23,40,41,88,93},		/* diag:pulse:period:calib:point - 81 */
		{23,40,45,88,94},		/* diag:pulse:delay:calib:shift - 82 */
		{23,32,88,93},			/* diag:ampl:calib:point - 83 */
		{23,33,88,93},			/* diag:offset:calib:point - 84 */
		{23,33,96,93},			/* diag:offset:null:point - 85 */
		{23,57,97},			/* diag:eprom:size - 86 */
		{83,84},			/* display:brightness - 87 */
		{28|optional,40,82},		/* sour:puls:count - 88 */
		{28|optional,40,98},		/* sour:puls:separation - 89 */
		{23,40,98,88,93},		/* diag:pulse:separation:calib:point - 90 */
		{13,68,99},			/* system:comm:network - 91 */
		{13,100,101},			/* system:password:new - 92 */
		{23,57,102},				/* diag:eprom:suspend - 93 */
		{28|optional,40,103,104|optional},	/* sour:puls:transition:leading - 94 */
		{23,40,103,88,93},			/* diag:pulse:transition:calib:point - 95 */
		{28|optional,29,105,32|optional},	/* sour:curr:limit:ampl - 96 */
		{23,24,85,88,93},			/* diag:output:load:calib:point - 97 */
		{28|optional,29,106},  		/* sour:curr:slew - 98 */
		{23,106,88,93},			/* diag:slew:calib:point - 99 */
		{88,107|optional},  		/* calibration:all - 100 */
		{88,37},			/* calibration:frequency - 101 */
		{23,57,108},			/* diag:eprom:reset - 102 */
		{23,109,16|optional},       	/* diag:attenuator:state - 103 */
		{23,32,110,88,93},              /* diag:ampl:distort:calib:point - 104 */
		{23,57,111},			/* diag:eprom:resize - 105 */
		{23,57,111,32}, 		/* diag:eprom:resize:ampl - 106 */
		{23,57,111,33},			/* diag:eprom:resize:offset - 107 */
		{23,88,112,113}			/* diag:cal:check:disable - 108 */
	};


	int token_num;		 /* which token in the command[] list is being considered */
	int sentence_num;	 /* which sentence is being considered as a match */
	int sentence_found;  /* matching sentence found yet? */
	int sent_pos;		  /* position in current sentence */
	int invalid_match;	/* flag if definitely the wrong match */
	int local_match_pos; /* position (or pos+1, depends) of most-recently-matched token in sentence */
	int local_match;	  /* match for current token found yet? */
	int prev_match;		/* were there previous local matches? */
	int i;					/* a counter */

	sentence_num = 1;
	sent_pos = 0;

	/* check each "sentence" (corresponding to a different routine or function)
		until a match is found, or until their are no possible sentences left */
	for (sentence_found = 0; (!sentence_found && sentence_num < max_no_of_sentences); ++sentence_num) {
		local_match_pos=0;
		invalid_match=0;
		prev_match=0;
		/* start with the first input token, until all have been matched, or one
		is unmatchable */
		for (token_num = 0; (token_num < command_depth) && !invalid_match; ++token_num) {
			/* start after most recent matching token */
			sent_pos=local_match_pos;

			/* compare current token to the sentence components until a matching component
				is found, or until there are none left */
			for (local_match=0; (!local_match) && (sent_pos<max_tokens_in_sentence); ++sent_pos) {

				/* compare here */
				if (commands[token_num]==((sentences[sentence_num][sent_pos]) & opt_mask)) {
					/* flag a local token match (not a whole sentence match) */
					local_match=1;
				}
			}
			if (local_match) {
				/* if any of the components in the sentence were skipped between the last two
					matches, make sure that they were optional ones */
				if (!prev_match) {
					local_match_pos=-1;
				}
				/* if there was no local match previously, then the initial value
					of local_match_pos is misleading - there was no match at 0. */
				for (i=(local_match_pos+1); i<(sent_pos-1); ++i) {
					/* if they weren't optional, the match is not valid */
					if (!(sentences[sentence_num][i] & optional)) {
						invalid_match=1;
					}
				}
				/* counteract the last "++i" due to the for loop */
				local_match_pos = sent_pos - 1;
				if (local_match && !invalid_match) {
					prev_match=1;
				}
			}

			/* if no match for this one token existed in this sentence, mark this sentence as invalid */
			if (!local_match) {
				invalid_match = 1;
			}
		}
		/* if no invalid token match was found for any of the tokens in this sentence,
			then it's an overall sentence match! */
		if (!invalid_match) {
			sentence_found=1;
		}
	}
	--sentence_num;

	if (!sentence_found) {
		sentence_num = 0;
	}
	/* 0 is the no-match value */

	return sentence_num;
}


static int Parser_get_unit(char **parameter, char **units)
{
	/* this function takes a parameter like "1e+6 ms" and breaks it into parameter="1e+6" and
		units="ms" */

	if (*parameter == NULL) {
		*parameter = g_strdup ("");
	}

	g_assert (*units == NULL);

	gchar *end_ptr;
	g_strtod (*parameter, &end_ptr);

	if (end_ptr == *parameter) {
		*units = g_strdup ("");
	} else {
		*units = g_strdup (end_ptr);
		end_ptr[0] = 0;	// truncates parameter
	}

	g_strstrip (*units);
	g_strstrip (*parameter);

	int units_present = (*units[0] != 0);
	return units_present;
}


static gchar* regex_replace (gchar* in_string, gchar* regex_string, gchar* replace_with)
{
	return conditional_regex_replace (TRUE, in_string, regex_string, replace_with);
}


static gchar* filter_input (gchar *raw_in)
{
	g_strstrip (raw_in);
	gchar *step0 = g_strdup (raw_in);

	// replace weird characters with a space
	gchar *step1 = regex_replace (step0, "[^\x20-\x7E]+", " ");
	g_free (step0);

	// replace multiple whitespace with single space
	gchar *step2 = regex_replace (step1, "\\s+", " ");
	g_free (step1);

	// remove spaces before and after semicolons in compound messages
	gchar *step3 = regex_replace (step2, "\\s*;\\s*", ";");
	g_free (step2);

	// remove semicolon at end
	gchar *step4 = regex_replace (step3, ";$", "");
	g_free (step3);

	// remove leading spaces, colons, semicolons
	gchar *step5 = regex_replace (step4, "^[\\s:;]*", "");
	g_free (step4);

	// last step may leave hanging whitespace at end
	g_strstrip (step5);

	// add single space to terminate
	gchar *filt = g_strdup_printf ("%s ", step5);
	g_free (step5);

	return filt;
}


void Parser_main (char *raw_in, int interactive_terminal, void(*cbfunc)(gpointer, gchar *), gpointer user_data)
{
	static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
	g_static_mutex_lock (&mutex);

	gchar **v;
	v = g_strsplit_set (raw_in, "\r\n", STDBUFSIZE);

	int str_chunk;

	for (str_chunk=0; v[str_chunk] > 0; ++str_chunk) {

		gchar *in = filter_input (v[str_chunk]);

		int in_pos;				 /* this identifies the single character of in being processed */
		int command_depth;		/* how many command words have been parsed */
		int old_command_depth;	/* save this if in case of a compound message */
		int commands[max_commands_in_input];			/* list of identified command tokens */
		int old_commands[max_commands_in_input];	  /* list of identified command tokens from */
		/* last non-common, non-colon-started command*/
		int space_found;		  /* if true, a space was found. parameter may follow */
		int parameter_found;	 /* if true, there is a parameter at the end of the command string */
		int semicolon_found;								 /* to break up lines */
		int units_found;		  /* text found after parameter must be units */
		int i;													/* counter */
		int routine_num;		  	/* routine to execute, based on command */
		int dont_use_this_header;	/* the old head is saved in case of compound message, unless this is set */
		int compound_message;		/* this indicates that at least one semicolon has been found, so */
		/* the message is a compound one */

		int is_query;
		int command_type;			/* combination of is_query, parameter_found, and units_found */

		int channel;
		int with_id_code;

		in_pos = 0;							 /* start at the beginning of the input string */
		semicolon_found = 0;
		compound_message = 0;
		command_depth=0;
		old_command_depth=0;
		dont_use_this_header=NO;

		/* examine each letter in the string until EOS */
		while (in[in_pos] != 0) {

			gchar *units = NULL;
			gchar *response = NULL;
			gchar *error_response = NULL;
			gchar *parameter = NULL;

			channel=-1;
			with_id_code=0;
			space_found = 0;
			parameter_found = 0;							 /* no numeric parameters yet */
			units_found = 0;
			is_query = 0;

			GString *current_word = g_string_new ("");

			if (semicolon_found && !dont_use_this_header) {
				old_command_depth=command_depth-2;
				for (i=0; i<old_command_depth; ++i) {
					old_commands[i]=commands[i];
				}
			}

			command_depth=old_command_depth;
			for (i=0; i<command_depth; ++i) {
				commands[i]=old_commands[i];
			}

			semicolon_found=0;
			dont_use_this_header=NO;

			/* break it up if semicolons are present */
			while (!semicolon_found && in[in_pos] != 0) {

				in[in_pos]=tolower(in[in_pos]);
				/* everything to lowercase */

				/* words are separated by white space or colons or semicolons */
				if ( isspace(in[in_pos]) || in[in_pos] == ':' || in[in_pos] == ';')

				{

					if (in[in_pos] == ';') {
						++semicolon_found;
					}
					++compound_message;

					/* if it is a separator, ignore it if it is duplicated */
					if ( !isspace(in[in_pos-1])  && (in[in_pos-1] != ':') && (in[in_pos-1] != ';')) {
						/* valid separator, so terminate current command word string */

						if (space_found) {
							/* Just end things if it is a semicolon */
							if (in[in_pos]!=';') {
								g_string_append_c (current_word, in[in_pos]);
							}

							++parameter_found;

							// the parameter may have multiple words,
							// so this branch may be called repeatedly
							g_free (parameter);
							parameter = g_strdup (current_word->str);

						} else if (!space_found) {
							/* end of a regular command word - use it */

							commands[command_depth]=Parser_id_word(	current_word->str,
												&channel,
												&with_id_code);

							/* get ready for the next token */
							g_string_free (current_word, 1);
							current_word = g_string_new ("");

							if (	  commands[command_depth]<13
									|| commands[command_depth]==63
									|| commands[command_depth]==64) {
								dont_use_this_header=YES;
								commands[0]=commands[command_depth];
								command_depth=0;
							}

							++command_depth;		  /* indicate that a new command word is ready */

							/* indicate if the separator was a space - next bit parameter then */
							if (in[in_pos]==' ') {
								++space_found;
							}
						}
					} /* non-repeated separator */
					else if (compound_message && in[in_pos-1]==';' && in[in_pos]==':') {
						dont_use_this_header=YES;
						command_depth=0;
					}

				} /* a separator */
				else if (in[in_pos]!='?') {
					/* if not white space or separator, add character to current command word */
					g_string_append_c (current_word, in[in_pos]);
				} /* not a separator */
				else {
					++is_query;
					/* question mark found */
				}


				++in_pos;							/* move pointer to next letter */

			} /* not a semi-colon */

			commands[command_depth]=0;
			++command_depth;
			/* add end of tokens marker (0) */

			int error_num=OK;

			units_found = Parser_get_unit(&parameter,&units);

			if (!globals.Sys.startup_complete) {
				error_num=Startup_Not_Finished;
			}

			if (!error_num) {
				command_type=(is_query<<2) | (parameter_found?2:0) | units_found;

				if (commands[0]!=0) {
					routine_num = Parser_find_commands(commands,command_depth);

					/* check for valid channel number, based on position in command */
					if ( (error_num=Parser_channel(&channel,with_id_code,routine_num)) )
						/* not a valid command due to improper channel suffix */
					{
						routine_num=9999;
					}
				} else {
					routine_num=9999;
					/* ignore empty commands lists, generated by a white space string */
				}

				switch (routine_num) {
				case 0:
					error_num=Unrecognized;
					break;

				case 1:
					error_num=Go_cls_1(&response,channel,parameter,units,command_type);
					break;
				case 2:
					error_num=Go_ese_2(&response,channel,parameter,units,command_type);
					break;
				case 3:
					error_num=Go_esr_3(&response,channel,parameter,units,command_type);
					break;
				case 4:
					error_num=Go_idn_5(&response,channel,parameter,units,command_type);
					break;
				case 5:
					error_num=Go_opc_5(&response,channel,parameter,units,command_type);
					break;
				case 6:
					error_num=Go_rst_6(&response,channel,parameter,units,command_type);
					break;
				case 7:
					error_num=Go_sre_7(&response,channel,parameter,units,command_type);
					break;
				case 8:
					error_num=Go_stb_8(&response,channel,parameter,units,command_type);
					break;
				case 9:
					error_num=Go_tst_9(&response,channel,parameter,units,command_type);
					break;
				case 10:
					error_num=Go_wai_10(&response,channel,parameter,units,command_type);
					break;
				case 11:
					error_num=Go_syst_err_11(&response,channel,parameter,units,command_type);
					break;
				case 12:
					error_num=Go_syst_ver_12(&response,channel,parameter,units,command_type);
					break;
				case 13:
				case 14:
				case 16:
				case 17:
					error_num=Go_event_13(&response,channel,parameter,units,command_type);
					break;
				case 15:
					error_num=Go_oper_enable15(&response,channel,parameter,units,command_type);
					break;
				case 18:
					error_num=Go_ques_enable18(&response,channel,parameter,units,command_type);
					break;
				case 19:
					error_num=Go_preset_19(&response,channel,parameter,units,command_type);
					break;
				case 20:
					error_num=Go_zout_20(&response,channel,parameter,units,command_type);
					break;
				case 21:
				case 30:
				case 31:
					error_num=Go_prot_trip_21(&response,channel,parameter,units,command_type);
					break;
				case 22:
					error_num=Go_ampl_26(&response,channel,parameter,units,command_type,"a");
					break;
				case 25:
					error_num=Go_offset_29(&response,channel,parameter,units,command_type,"a");
					break;
				case 26:
					error_num=Go_ampl_26(&response,channel,parameter,units,command_type,"v");
					break;
				case 29:
					error_num=Go_offset_29(&response,channel,parameter,units,command_type,"v");
					break;
				case 32:
				case 33:
					error_num=Go_freq_32_33(&response,channel,parameter,units,command_type);
					break;
				case 34:
					error_num=Go_func_34(&response,channel,parameter,units,command_type);
					break;
				case 35:
					error_num=Go_period_35(&response,channel,parameter,units,command_type);
					break;
				case 36:
					error_num=Go_pw_36(&response,channel,parameter,units,command_type);
					break;
				case 37:
					error_num=Go_duty_37(&response,channel,parameter,units,command_type);
					break;
				case 38:
					error_num=Go_hold_38(&response,channel,parameter,units,command_type);
					break;
				case 39:
				case 41:
					error_num=Go_delay_39(&response,channel,parameter,units,command_type);
					break;
				case 40:
					error_num=Go_dbl_pulse_40(&response,channel,parameter,units,command_type);
					break;
				case 42:
					error_num=Go_polarity_42(&response,channel,parameter,units,command_type);
					break;
				case 46:
					error_num=Go_trig_source46(&response,channel,parameter,units,command_type);
					break;
				case 47:
					error_num=Go_Str_eprom_47(&response,channel,parameter,units,command_type);
					break;
				case 48:
					error_num=Go_int_eprom_48(&response,channel,parameter,units,command_type);
					break;
				case 51:
					error_num=Go_Float_eprom51(&response,channel,parameter,units,command_type);
					break;
				case 53:
					error_num=Go_rcl_53(&response,channel,parameter,units,command_type);
					break;
				case 54:
					error_num=Go_sav_54(&response,channel,parameter,units,command_type);
					break;
				case 55:
					error_num=Go_output_55(&response,channel,parameter,units,command_type);
					break;
				case 56:
					error_num=Go_gate_type_56(&response,channel,parameter,units,command_type);
					break;
				case 58:
					error_num=Go_delay_test58(&response,channel,parameter,units,command_type);
					break;
				case 59:
					error_num=Go_gpib_addr_59(&response,channel,parameter,units,command_type);
					break;
				case 60:
					error_num=Go_ser_baud_60(&response,channel,parameter,units,command_type);
					break;
				case 64:
					error_num=Go_ser_rts_64(&response,channel,parameter,units,command_type);
					break;
				case 66:
					error_num=Go_syst_errcnt66(&response,channel,parameter,units,command_type);
					break;
				case 67:
					error_num=Go_gate_level_67(&response,channel,parameter,units,command_type);
					break;
				case 68:
					error_num=Go_load_68(&response,channel,parameter,units,command_type);
					break;
				case 69:
					error_num=Go_meas_ampl_69(&response,channel,parameter,units,command_type);
					break;
				case 70:
					error_num=Go_char_eprom_70(&response,channel,parameter,units,command_type);
					break;
				case 72:
					error_num=Go_calib_amp_72(&response,channel,parameter,units,command_type);
					break;
				case 73:
					error_num=Go_calib_mon_73(&response,channel,parameter,units,command_type);
					break;
				case 74:
					error_num=Go_mon_step_74(&response,channel,parameter,units,command_type);
					break;
				case 75:
					error_num=Go_outputtype_75(&response,channel,parameter,units,command_type);
					break;
				case 76:
					error_num=Go_calib_os_76(&response,channel,parameter,units,command_type);
					break;
				case 77:
					error_num=Go_calib_pw_77(&response,channel,parameter,units,command_type);
					break;
				case 78:
					error_num=Go_routeclose_78(&response,channel,parameter,units,command_type);
					break;
				case 79:
					error_num=Go_amp_pnt_83(&response,channel,parameter,units,command_type,pwl_pw_values);
					break;
				case 80:
					error_num=Go_amp_pnt_83(&response,channel,parameter,units,command_type,pwl_delay_values);
					break;
				case 81:
					error_num=Go_amp_pnt_83(&response,channel,parameter,units,command_type,pwl_period_values);
					break;
				case 82:
					error_num=Go_dly_shift_82(&response,channel,parameter,units,command_type);
					break;
				case 83:
					error_num=Go_amp_pnt_83(&response,channel,parameter,units,command_type,pwl_ampl_values);
					break;
				case 84:
					error_num=Go_amp_pnt_83(&response,channel,parameter,units,command_type,pwl_os_values);
					break;
				case 86:
					error_num=Go_eprom_siz_86(&response,channel,command_type);
					break;
				case 88:
					error_num=Go_puls_count_88(&response,channel,parameter,units,command_type);
					break;
				case 89:
					error_num=Go_puls_sep_89(&response,channel,parameter,units,command_type);
					break;
				case 90:
					error_num=Go_amp_pnt_83(&response,channel,parameter,units,command_type,pwl_burst_values);
					break;
				case 91:
					error_num=Go_sys_net_91(&response,channel,parameter,units,command_type);
					break;
				case 92:
					error_num=Go_sys_pwd_92(&response,channel,parameter,command_type);
					break;
				case 93:
					error_num=Go_eprom_sus_93(&response,channel,parameter,command_type);
					break;
				case 94:
					error_num=Go_rise_time_94(&response,channel,parameter,units,command_type);
					break;
				case 95:
					error_num=Go_amp_pnt_83(&response,channel,parameter,units,command_type,pwl_rise_time_values);
					break;
				case 96:
					error_num=Go_soft_current_limit_96(&response,channel,parameter,units,command_type);
					break;
				case 98:
					error_num=Go_curr_slew_98(&response,channel,parameter,units,command_type);
					break;
				case 99:
					error_num=Go_amp_pnt_83(&response,channel,parameter,units,command_type,pwl_slew_values);
					break;
				case 100:
					error_num=Go_cal_100(&response,channel,parameter,units,command_type);
					break;
				case 101:
					error_num=Go_cal_interval_101(&response,channel,parameter,units,command_type);
					break;
				case 102:
					error_num=Go_eprom_reset_102(&response,channel,parameter,units,command_type);
					break;
				case 103:
					error_num=Go_atten_103(&response,channel,parameter,units,command_type);
					break;
				case 104:
					error_num=Go_amp_pnt_83(&response,channel,parameter,units,command_type,pwl_distort_values);
					break;
				case 105:
					error_num=Go_eprom_resize_105(&response,channel,parameter,units,command_type);
					break;
				case 106:
					error_num=Go_eprom_resize_ampl_106(&response,channel,parameter,units,command_type);
					break;
				case 107:
					error_num=Go_eprom_resize_offset_107(&response,channel,parameter,units,command_type);
					break;
				case 108:
                                        error_num=Go_cal_checking_disable_108(&response,channel,parameter,units,command_type);
                                        break;

				case 9999:
					// was only whitespace, ignore
					break;

				default:
					error_num=Unrecognized;
					break;

				}
			}

			if (error_num) {
				queue_error_from_parser(&error_response, error_num);
				if (interactive_terminal) {
					(*cbfunc)(user_data, error_response);
				}
			} else if (response != NULL) {
				(*cbfunc)(user_data, response);
			}

			g_free (units);
			g_free (response);
			g_free (error_response);
			g_free (parameter);
			g_string_free (current_word, 1);

			if (!is_query) {
				Main_update_shift_registers();    /* update values in pulse generator circuit */
			}

		} /* not EOS */

		/* update display if it wasn't a query, and if the control menu isn't on (this gives the user
		a chance to press "Go To Local" to override control */
		if (!is_query && !(globals.MenuStatus.Selected_Submenu==Submenu1_rem_loc && globals.MenuStatus.Type_Of_Menu==Submenu_On)) {
			Show_Main_Menu();
		}

		/* re-run error_check to update min/max values based on actual settings, not proposed settings */
		Error_check(globals.ChannelState);

		g_free (in);
	}
	g_strfreev (v);

	// trigger a prompt
	if (interactive_terminal) {
		(*cbfunc)(user_data, "");
	}

	g_static_mutex_unlock (&mutex);
}


static int Parser_channel (int *channel,int with_id_code,int routine_num)
{
	/* return if no channel suffixes appeared */
	if (*channel==-1) {
		*channel=0;
		return OK;
	}


	/* compare to maximum number of channels allowed */
	if (*channel>1 && *channel>globals.Flash.channels) {
		return InvalidChannel;
	}


	/* SCPI uses 1-N counting, change to 0 - (N-1) */
	if (*channel > 0) {
		--(*channel);
	} else {
		return InvalidChannel;
	}

	return OK;
}


static int Go_freq_32_33(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	float new_freq;
	int status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_frequency)) {
		return status;
	}

	new_freq=1.0;

	switch (command_type) {
	case command_param_units:
		if (status=Handle_Units(&new_freq,units,"hz")) {
			return status;
		}
		/* no break */

	case command_withparam:
		if (status = process_float_param (parameter, &new_freq, globals.Constraints.err_min_freq[channel], globals.Constraints.err_max_freq[channel], NORMAL_ZERO)) {
			return status;
		}
		return Set_frequency(0,0,0,channel,new_freq);
		break;

	case query_simple:
		return query_float(response, globals.ChannelState[channel].frequency);
		break;

	case query_param:
		return query_min_max_float (response, parameter, globals.Constraints.err_min_freq[channel], globals.Constraints.err_max_freq[channel]);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_Str_eprom_47(gchar** response, int channel, char *loc_string,char *store_string,int command_type)
{
	/* diag:eprom:string - 47 */
	int eprom_loc;

	if (!String_is_it_pos_int(loc_string)) {
		return SyntaxError;
	}

	eprom_loc = atoi(loc_string);
	/* convert location string to a number */

	if ((eprom_loc < 0) || (eprom_loc>sizeof(globals.Flash))) {
		return OutOfRange;
	}

	switch (command_type) {
	case command_param_units:
		if ( (strlen(store_string) < sizeof(globals.Flash.model_num)) && (eprom_loc >= 0)) {
			int i;
			for (i=0; i<strlen(store_string); ++i) {
				/* convert ~ to spaces */
				if (store_string[i]=='~') {
					store_string[i]=' ';
				}
				*(char *)(&globals.Flash.flash_start + eprom_loc+i)=g_ascii_toupper(store_string[i]);
			}
			*(char *)(&globals.Flash.flash_start + eprom_loc + i)=(char) 0;  /* end of string */
			writeUserBlock(&globals.Flash, eprom_loc, strlen(store_string)+1);
			return OK;
		} else {
			return OutOfRange;
		}
		break;

	case query_param:
		return query_string (response, (char *)(&globals.Flash.flash_start + eprom_loc));
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_int_eprom_48(gchar** response, int channel, char *loc_string,char *store_string,int command_type)
{
	/* diag:eprom:int - 48 */
	int eprom_loc;
	short the_number;

	if (!String_is_it_pos_int(loc_string)) {
		return SyntaxError;
	}

	eprom_loc = atoi(loc_string);
	/* convert location string to a number */

	if ((eprom_loc < 0) || (eprom_loc>sizeof(globals.Flash))) {
		return OutOfRange;
	}

	switch (command_type) {
	case command_param_units:
		if (!String_is_it_pos_neg_int(store_string)) {
			return SyntaxError;
		}
		the_number=(short) atoi(store_string);
		*(short *)(&globals.Flash.flash_start + eprom_loc) = the_number;
		writeUserBlock(&globals.Flash, eprom_loc, sizeof (the_number));
		return OK;
		break;

	case query_param:
		return query_int (response, (int) *(short *)(&globals.Flash.flash_start + eprom_loc));
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_Float_eprom51(gchar** response, int channel, char *loc_string,char *store_string,int command_type)
{
	/* diag:eprom:float - 51 */
	int eprom_loc;
	float the_number;

	if (!String_is_it_pos_int(loc_string)) {
		return SyntaxError;
	}

	eprom_loc = atoi(loc_string);

	/* convert location string to a number */

	if ((eprom_loc < 0) || (eprom_loc>sizeof(globals.Flash))) {
		return OutOfRange;
	}

	switch (command_type) {
	case command_param_units:
		if (!String_is_it_numeric(store_string)) {
			return SyntaxError;
		}
		the_number=atof(store_string);
		*(float *)(&globals.Flash.flash_start + eprom_loc)=the_number;
		writeUserBlock(&globals.Flash, eprom_loc, sizeof(the_number));
		return OK;
		break;

	case query_param:{
		// The basic issue here is that this pointer isn't aligned. Which
		// should actually be a problem as ARMv7 has unaligned access support
		// and it's hardcoded to be on.. the issue is that not all instructions
		// can do unaliged accesses and the previous code generated one of those
		// instructions. The kernel traps the access and kills the process.
		// You should see something like this in dmesg:
		// [494223.471575] Alignment trap: not handling instruction edd37a00 at [<00011d12>]
		// [494223.479380] Unhandled fault: alignment exception (0x001) at 0x00050d66
		//
		// I use memcpy here to copy the variable out into a temp
		// variable on the stack which is aligned.
		// There are probably other bits of code that will trigger this because of
		// the use of offsets into the struct.. It might be an idea to write some macros
		// for pushing and pulling bits from the struct.
		float temp;
		memcpy(&temp, (float *)(&globals.Flash.flash_start + eprom_loc),sizeof(float));
		return query_float(response, temp);
	}
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_char_eprom_70(gchar** response, int channel, char *loc_string,char *store_string,int command_type)
{
	/* diag:eprom:char - 70 */
	int eprom_loc;
	char the_number;

	if (!String_is_it_pos_int(loc_string)) {
		return SyntaxError;
	}

	eprom_loc = atoi(loc_string);
	/* convert location string to a number */

	if ((eprom_loc < 0) || (eprom_loc>sizeof(globals.Flash))) {
		return OutOfRange;
	}

	switch (command_type) {
	case command_param_units:
		if (!String_is_it_pos_int(store_string)) {
			return SyntaxError;
		}
		the_number=(char) atoi(store_string);
		*(char *)(&globals.Flash.flash_start + eprom_loc)=the_number;
		writeUserBlock(&globals.Flash, eprom_loc, sizeof(the_number));

		return OK;
		break;

	case query_param:
		return query_int (response, (int) *(char *)(&globals.Flash.flash_start + eprom_loc));
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_eprom_siz_86(gchar** response, int channel, int command_type)
{
	switch (command_type) {
	case query_simple:
		return query_int (response, sizeof(globals.Flash));
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_sys_net_91(gchar **response, int channel, char *parameter,char *units,int command_type)
{
	nicinfo info;

	switch (command_type) {
	case query_simple:
		if (nicutils_infofordefaultroute(&info)) {
			*response = g_strdup_printf ("MAC address: %s, IP address: %s", info.mac, info.ip);
			return OK;
		} else {
			return NetworkNotFound;
		}
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Handle_Units(float *mult,char *units, char *in_base)
{
	int len_base, len_all, pos;
	int errornum = OK;

	*mult=1.0;
	if (!strcmp(units,in_base)) {
		return OK;
	}

	len_all = strlen (units);
	if (len_all == 0) {
		return OK;
	}

	gchar *prefix = g_strdup (units);
	gchar *base = g_strdup (in_base);

	len_base = strlen (base);
	pos = len_all - len_base;

	if (!strcmp(base,"%") && (len_all >= 3) && !strcmp(prefix + len_all - 3,"pct")) {
		g_free (base);
		base = g_strdup ("pct");
		prefix[len_all - 3] = 0;
	} else if (!strcmp(base,"pct") && !strcmp(prefix + len_all - 1,"%")) {
		g_free (base);
		base = g_strdup ("%");
		prefix[len_all - 1] = 0;
	} else if (strcmp(prefix+pos,base)) {
		errornum = UnknownUnits;
	} else {
		prefix[pos]=0;
	}

	if (strlen(prefix) && !errornum) {

		// special exceptions
		if (!strcmp(prefix,"m") && !strcmp(base,"ohm")) {
			*mult=1.0e6;
		} else if (!strcmp(prefix,"m") && !strcmp(base,"hz")) {
			*mult=1.0e6;
		}
		// normal rules
		else if (!strcmp(prefix,"ex")) {
			*mult=1.0e18;
		} else if (!strcmp(prefix,"pe")) {
			*mult=1.0e15;
		} else if (!strcmp(prefix,"t")) {
			*mult=1.0e12;
		} else if (!strcmp(prefix,"g")) {
			*mult=1.0e9;
		} else if (!strcmp(prefix,"ma")) {
			*mult=1.0e6;
		} else if (!strcmp(prefix,"k")) {
			*mult=1.0e3;
		} else if (!strcmp(prefix,"m")) {
			*mult=1.0e-3;
		} else if (!strcmp(prefix,"u")) {
			*mult=1.0e-6;
		} else if (!strcmp(prefix,"n")) {
			*mult=1.0e-9;
		} else if (!strcmp(prefix,"p")) {
			*mult=1.0e-12;
		} else if (!strcmp(prefix,"f")) {
			*mult=1.0e-15;
		} else if (!strcmp(prefix,"a")) {
			*mult=1.0e-18;
		} else {
			errornum = UnknownUnits;
		}
	}

	g_free (base);
	g_free (prefix);

	return errornum;
}


static int Is_Min_Command(gchar *text)
{
	return (!strcmp(text,"min") || !strcmp(text,"minimum"));
}


static int Is_Max_Command(char *text)
{
	return (!strcmp(text,"max") || !strcmp(text,"maximum"));
}

static int query_int (gchar** response, int n)
{
	*response = g_strdup_printf ("%d", n);
	return OK;
}

static int query_min_max_int (gchar** response, char *parameter, int min_val, int max_val)
{
	int report_val;

	if (Is_Min_Command(parameter)) {
		report_val=min_val;
	} else if (Is_Max_Command(parameter)) {
		report_val=max_val;
	} else {
		return SyntaxError;
	}

	*response = g_strdup_printf ("%d", report_val);
	return OK;
}

static int query_min_max_float (gchar** response, char *parameter, float min_val, float max_val)
{
	float report_val;

	if (Is_Min_Command(parameter)) {
		report_val=min_val;
	} else if (Is_Max_Command(parameter)) {
		report_val=max_val;
	} else {
		return SyntaxError;
	}

	Float_To_Text(remote_digits_after_decimal,report_val,response);
	return OK;
}

static int query_float (gchar** response, float value)
{
	Float_To_Text(remote_digits_after_decimal,value,response);
	return OK;
}

static int query_string (gchar** response, char *in)
{
	*response = g_strdup (in);
	return OK;
}

static int process_float_param (char *parameter, float *value, float min_val, float max_val, int zero_mode)
{
	int status;
	status = OK;

	if (String_is_it_numeric(parameter)) {
		*value *= atof(parameter);

		if (zero_mode == ALLOW_NEG_ZERO) {
			/* allow a value of "-0" */
			if (fabs(*value) < smallest_allowed_number)
				if (parameter[0] == '-') {
					*value = -0.1*smallest_allowed_number;
				}
		}
	}

	else if (!strcmp(parameter,"+") && (zero_mode == ALLOW_NEG_ZERO)) {
		*value = smallest_allowed_number;
	} else if (!strcmp(parameter,"-") && (zero_mode == ALLOW_NEG_ZERO)) {
		*value = -smallest_allowed_number;
	} else if (Is_Min_Command(parameter)) {
		*value = min_val;
	} else if (Is_Max_Command(parameter)) {
		*value = max_val;
	} else {
		status=SyntaxError;
	}

	return status;
}

#define USE_ON_OFF 0
#define NO_ON_OFF 1
static int process_int_param (char *parameter, int *value, int item_count, int *valid_nums, int allow_on_off)
{
	int status, min_val, max_val, is_valid;

	status = OK;
	is_valid = 0;

	min_val = valid_nums[0];
	max_val = valid_nums[item_count - 1];

	if (String_is_it_pos_int(parameter)) {
		*value = atoi(parameter);
		int i;
		for (i = 0; (i < item_count) && (is_valid == 0); i++) {
			if (*value == valid_nums[i]) {
				is_valid = 1;
			}
		}
		if (is_valid == 0) {
			status = IllegalParameter;
		}
	} else if (!strcmp(parameter,"off") && (allow_on_off == USE_ON_OFF)) {
		*value = 0;
	} else if (!strcmp(parameter,"on") && (allow_on_off == USE_ON_OFF)) {
		*value = 1;
	} else if (Is_Min_Command(parameter) && (allow_on_off == NO_ON_OFF)) {
		*value = min_val;
	} else if (Is_Max_Command(parameter) && (allow_on_off == NO_ON_OFF)) {
		*value = max_val;
	} else {
		status=SyntaxError;
	}

	return status;
}

static int process_int_range (char *parameter, int *value, int min_val, int max_val)
{
	int status;
	status = OK;

	if (String_is_it_pos_int(parameter)) {
		*value = atoi(parameter);
		if ((*value<min_val) || (*value>max_val)) {
			status = OutOfRange;
		}
	} else if (Is_Min_Command(parameter)) {
		*value = min_val;
	} else if (Is_Max_Command(parameter)) {
		*value = max_val;
	} else {
		status=SyntaxError;
	}

	return status;
}

static int process_on_off (char *parameter, int *value)
{
	int valid_choices[2] = {0, 1};
	return process_int_param (parameter, value, 2, valid_choices, USE_ON_OFF);
}

static int process_two_ints (char *parameter, int *value, int min, int max)
{
	int valid_choices[2] = {min, max};
	return process_int_param (parameter, value, 2, valid_choices, NO_ON_OFF);
}

static int check_channel_ok (int channel, int enabled_channels, char chankey)
{
	/* how many channels overall */
	if (channel >= enabled_channels) {
		return InvalidChannel;
	}

	/* abandon if high channel selected by user but not enabled by firmware for that parameter*/
	if (channel && !chankey) {
		return InvalidChannel;
	}

	return OK;
}

static int Go_syst_err_11(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	switch (command_type) {
	case query_simple:
		if (globals.Errors.number_of_errors==0) {
			get_error_text(response, OK);
		} else {
			get_error_text(response,globals.Errors.error_queue[1]);
			Error_Remove_From_Queue();
		}
		return OK;
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}

static int Go_syst_errcnt66(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	switch (command_type) {
	case query_simple:
		return query_int (response, globals.Errors.number_of_errors);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_ampl_26(gchar** response, int channel, char *parameter,char *units,int command_type,char *mode)
{
	float new_ampl;
	int status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_amplitude)) {
		return status;
	}
	if (!strcmp(mode,"v")) {
		if (!globals.Flash.voltage_enabled[channel]) {
			return Unrecognized;
		}
	}
	if (!strcmp(mode,"a") && !globals.Flash.current_enabled[channel]) {
		return Unrecognized;
	}

	new_ampl=1.0;

	switch (command_type) {
	case command_param_units:
		if (status=Handle_Units(&new_ampl,units,mode)) {
			return status;
		}
		/* no break */

	case command_withparam:
		if (!strcmp(parameter,"ext") || !strcmp(parameter,"external")) {
			return Set_EA(channel,amp_mode_ea);
		} else if (!strcmp(parameter,"amp") || !strcmp(parameter,"amplify")) {
			return Set_EA(channel,amp_mode_amplify);
		} else if (status = process_float_param (parameter, &new_ampl, globals.Constraints.err_min_ampl[channel], globals.Constraints.err_max_ampl[channel], ALLOW_NEG_ZERO)) {
			return status;
		}

		Set_EA(channel,amp_mode_normal);
		return Set_Amplitude(0,0,0,0,0,0,0,channel,new_ampl,0);
		break;

	case query_simple:
		if (globals.ChannelState[channel].amp_mode==amp_mode_ea) {
			return query_string(response, "EXT");
		} else if (globals.ChannelState[channel].amp_mode==amp_mode_amplify) {
			return query_string(response, "AMP");
		} else {
			if (globals.Flash.ignore_ampl_polarity[channel]) {
				return query_float(response, fabs(globals.ChannelState[channel].amplitude));
			} else {
				return query_float(response, globals.ChannelState[channel].amplitude);
			}
		}
		break;

	case query_param:
		return query_min_max_float (response, parameter, globals.Constraints.err_min_ampl[channel], globals.Constraints.err_max_ampl[channel]);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_pw_36(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	float new_pw;
	int status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_pw)) {
		return status;
	}
	if (globals.Flash.fixed_pw[channel]) {
		return Unrecognized;
	}

	new_pw=1.0;

	switch (command_type) {
	case command_param_units:
		if (status=Handle_Units(&new_pw,units,"s")) {
			return status;
		}
		/* no break */

	case command_withparam:
		if (!strcmp(parameter,"in")) {
			return Set_Pwmode(channel,pw_in_out);
		} else if (!strcmp(parameter,"ext")) {
                        return Set_Pwmode(channel,pw_ew_ext);
		} else if (status = process_float_param (parameter, &new_pw, globals.Constraints.err_min_pw[channel], globals.Constraints.err_max_pw[channel], NORMAL_ZERO)) {
			return status;
		}

		if (status = Set_Pwmode(channel,pw_normal)) {
			return status;
		}
		return Set_Pw(0,0,0,channel,new_pw,0);
		break;

	case query_simple:
		switch (globals.ChannelState[channel].pw_ctrl_mode) {
		case pw_in_out:
			return query_string(response, "IN");
			break;
                case pw_ew_ext:
                        return query_string(response, "EXT");
                        break;
		default:
		case pw_normal:
			return query_float(response, globals.ChannelState[channel].pw);
			break;
		}

		break;

	case query_param:
		return query_min_max_float (response, parameter, globals.Constraints.err_min_pw[channel], globals.Constraints.err_max_pw[channel]);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_duty_37(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	float new_duty;
	int status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_pw)) {
		return status;
	}
	if (globals.ChannelState[channel].trigger_source!=source_internal) {
		return DutyTriggerError;
	}

	new_duty=1.0;

	switch (command_type) {
	case command_param_units:
		if (status=Handle_Units(&new_duty,units,"%")) {
			return status;
		}
		/* no break */

	case command_withparam:
		if (status = process_float_param (parameter, &new_duty, globals.Constraints.err_min_pw[channel]*globals.ChannelState[channel].frequency*100, globals.Constraints.err_max_pw[channel]*globals.ChannelState[channel].frequency*100, NORMAL_ZERO)) {
			return status;
		}
		return Set_Pw(0,0,0,channel,new_duty/(100*globals.ChannelState[channel].frequency),0);
		break;

	case query_simple:
		return query_float(response, 100*globals.ChannelState[channel].pw*globals.ChannelState[channel].frequency);
		break;

	case query_param:
		return query_min_max_float (response, parameter, globals.Constraints.err_min_pw[channel]*globals.ChannelState[channel].frequency*100, globals.Constraints.err_max_pw[channel]*globals.ChannelState[channel].frequency*100);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}



static int Go_offset_29(gchar** response, int channel, char *parameter,char *units,int command_type,char *mode)
{
	float new_offset;
	int status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_offset)) {
		return status;
	}
	if (!strcmp(mode,"v") && !globals.Flash.voltage_offset_enabled[channel]) {
		return Unrecognized;
	}
	if (!strcmp(mode,"a") && !globals.Flash.current_offset_enabled[channel]) {
		return Unrecognized;
	}

	new_offset=1.0;

	switch (command_type) {
	case command_param_units:
		if (status=Handle_Units(&new_offset,units,mode)) {
			return status;
		}
		/* no break */

	case command_withparam:
		if (!strcmp(parameter,"ext") || !strcmp(parameter,"external")) {
			return Set_EO(channel,os_mode_eo);
		} else if (status = process_float_param (parameter, &new_offset, globals.Constraints.err_min_offset[channel], globals.Constraints.err_max_offset[channel], NORMAL_ZERO)) {
			return status;
		}

		Set_EO(channel,os_mode_normal);
		return Set_Offset(0,0,0,0,channel,new_offset);
		break;

	case query_simple:
		if (globals.ChannelState[channel].os_mode) {
			return query_string(response, "EXT");
		} else {
			return query_float(response, globals.ChannelState[channel].offset);
		}
		break;

	case query_param:
		return query_min_max_float (response, parameter, globals.Constraints.err_min_offset[channel], globals.Constraints.err_max_offset[channel]);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_idn_5(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	/* *idn? - 5 */

	switch (command_type) {
	case query_simple:
		idn_string(response);
		return OK;
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_period_35(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	float new_period;
	float min_period;
	float max_period;
	int status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_frequency)) {
		return status;
	}

	new_period=1.0;

	switch (command_type) {
	case command_param_units:
		if (status=Handle_Units(&new_period,units,"s")) {
			return status;
		}
		/* no break */

	case command_withparam:
		min_period = 1.0/globals.Constraints.err_max_freq[channel];

		max_period = globals.Constraints.err_min_freq[channel];
		if (max_period==0.0) {
			return OutOfRange;
		} else {
			max_period = 1.0/max_period;
		}

		if (status = process_float_param (parameter, &new_period, min_period, max_period, NORMAL_ZERO)) {
			return status;
		}
		return Set_frequency(0,0,0,channel,1.0/new_period);
		break;

	case query_simple:
		return query_float(response, 1/globals.ChannelState[channel].frequency);
		break;

	case query_param:
		return query_min_max_float (response, parameter, 1.0/globals.Constraints.err_max_freq[channel], 1.0/globals.Constraints.err_min_freq[channel]);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_delay_39(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	float new_delay;
	int status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_delay)) {
		return status;
	}

	if (!(globals.Flash.max_delay[channel]>0.0)) {
		return Unrecognized;
	}

	new_delay=1.0;

	switch (command_type) {
	case command_param_units:
		if (status=Handle_Units(&new_delay,units,"s")) {
			return status;
		}
		/* no break */

	case command_withparam:
		if (status = process_float_param (parameter, &new_delay, globals.Constraints.err_min_delay[channel], globals.Constraints.err_max_delay[channel], NORMAL_ZERO)) {
			return status;
		}
		return Set_Delay(0,0,0,channel,new_delay);
		break;

	case query_simple:
		return query_float(response, globals.ChannelState[channel].delay);
		break;

	case query_param:
		return query_min_max_float (response, parameter, globals.Constraints.err_min_delay[channel], globals.Constraints.err_max_delay[channel]);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_dbl_pulse_40(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int on_off, status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_double_pulse)) {
		return status;
	}
	if (!(globals.Flash.double_pulse_allowed[channel])) {
		return Unrecognized;
	}

	switch (command_type) {
	case command_withparam:
		if (status=process_on_off (parameter, &on_off)) {
			return status;
		}
		return Set_Double(channel,on_off);
		break;

	case query_simple:
		return query_int (response, globals.ChannelState[channel].double_pulse);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_func_34(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_func_mode)) {
		return status;
	}

	switch (command_type) {
	case command_withparam:
		if (!strcmp(parameter,"dc")) {
			return Set_Func(channel,dc_mode_on);
		} else if (!strcmp(parameter,"pulse") || !strcmp(parameter,"puls")) {
			return Set_Func(channel,pulse_mode_on);
		} else if (!strcmp(parameter,"sinusoid") || !strcmp(parameter,"sin") || !strcmp(parameter,"sine")) {
			return Set_Func(channel,sin_mode_on);
		} else if (!strcmp(parameter,"triangle") || !strcmp(parameter,"tri")) {
			return Set_Func(channel,tri_mode_on);
		} else if (!strcmp(parameter,"square") || !strcmp(parameter,"squ")) {
			return Set_Func(channel,squ_mode_on);
		} else if (!strcmp(parameter,"amplify") || !strcmp(parameter,"amp")) {
			return Set_Func(channel,amp_mode_on);
		} else {
			return SyntaxError;
		}
		break;

	case query_simple:
		if (globals.ChannelState[channel].func_mode==dc_mode_on) {
			return query_string(response, "DC");
		} else if (globals.ChannelState[channel].func_mode==pulse_mode_on) {
			return query_string(response, "PULSE");
		} else if (globals.ChannelState[channel].func_mode==sin_mode_on) {
			return query_string(response, "SIN");
		} else if (globals.ChannelState[channel].func_mode==tri_mode_on) {
			return query_string(response, "TRI");
		} else if (globals.ChannelState[channel].func_mode==squ_mode_on) {
			return query_string(response, "SQU");
		} else if (globals.ChannelState[channel].func_mode==amp_mode_on) {
			return query_string(response, "AMP");
		}
		return OK;
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_polarity_42(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_inverted)) {
		return status;
	}
	if (!(globals.Flash.invert_allowed[channel])) {
		return Unrecognized;
	}

	switch (command_type) {
	case command_withparam:
		if (!strcmp(parameter,"norm") || !strcmp(parameter,"normal")) {
			return Set_Inverted(channel,NO);
		} else if (!strcmp(parameter,"comp") || !strcmp(parameter,"complement")
		                || !strcmp(parameter,"inv") || !strcmp(parameter,"inverted") )

		{
			return Set_Inverted(channel,YES);
		} else {
			return SyntaxError;
		}
		break;

	case query_simple:
		if (globals.ChannelState[channel].inverted==NO) {
			return query_string(response, "NORM");
		} else {
			return query_string(response, "COMP");
		}
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_hold_38(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_hold_setting)) {
		return status;
	}

	switch (command_type) {
	case command_withparam:
		if (!strcmp(parameter,"widt") || !strcmp(parameter,"width")) {
			Set_Hold(channel,hold_width);
			return OK;
		} else if (!strcmp(parameter,"dcyc") || !strcmp(parameter,"dcycle")) {
			Set_Hold(channel,hold_duty);
			return OK;
		} else {
			return SyntaxError;
		}
		break;

	case query_simple:
		if (globals.ChannelState[channel].hold_setting==hold_width) {
			return query_string(response, "WIDT");
		} else {
			return query_string(response, "DCYC");
		}
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_output_55(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int on_off, status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_output_state)) {
		return status;
	}
	if(!globals.Flash.on_off_used) {
		return Unrecognized;
	}

	switch (command_type) {
	case command_withparam:
		if (status=process_on_off (parameter, &on_off)) {
			return status;
		}
		return Set_Output_State(channel,on_off);
		break;

	case query_simple:
		return query_int (response, globals.ChannelState[channel].output_state);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_trig_source46(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_trigger_source)) {
		return status;
	}

	if (globals.Flash.is_func_gen[channel]) {
		return Unrecognized;
	}

	switch (command_type) {
	case command_withparam:
		if (!strcmp(parameter,"int") || !strcmp(parameter,"internal")) {
			return Set_Trig_Source(channel,source_internal);
		} else if (!strcmp(parameter,"ext") || !strcmp(parameter,"external")) {
			return Set_Trig_Source(channel,source_external);
                } else if (!strcmp(parameter,"externaldouble") || !strcmp(parameter,"extdbl")) {
                        return Set_Trig_Source(channel,source_external2);
		} else if (!strcmp(parameter,"man") || !strcmp(parameter,"manual")) {
			return Set_Trig_Source(channel,source_manual);
		} else if (!strcmp(parameter,"hold")) {
			return Set_Trig_Source(channel,source_hold);
		} else if (!strcmp(parameter,"imm") || !strcmp(parameter,"immediate")) {
			return Set_Trig_Source(channel,source_immediate);
		} else {
			return SyntaxError;
		}
		break;

	case query_simple:
		if (globals.ChannelState[channel].trigger_source==source_internal) {
			return query_string(response, "INT");
		} else if (globals.ChannelState[channel].trigger_source==source_external) {
			return query_string(response, "EXT");
                } else if (globals.ChannelState[channel].trigger_source==source_external2) {
                        return query_string(response, "EXTDBL");
		} else if (globals.ChannelState[channel].trigger_source==source_manual) {
			return query_string(response, "MAN");
		} else if (globals.ChannelState[channel].trigger_source==source_hold) {
			return query_string(response, "HOLD");
		} else if (globals.ChannelState[channel].trigger_source==source_immediate) {
			return query_string(response, "IMM");
		}
		return OK;
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_gate_type_56(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_gate_type)) {
		return status;
	}
	if (globals.Flash.is_func_gen[channel]) {
		return Unrecognized;
	}

	switch (command_type) {
	case command_withparam:
		if (!strcmp(parameter,"sync")) {
			return Set_Gate_Sync(channel,gate_sync);
		} else if (!strcmp(parameter,"async")) {
			/* async mode doesn't work properly in dual-channel units */
			if ( (globals.Flash.channels>1) || globals.Flash.sync_only) {
				return AsyncModeDisabled;
			}

			return Set_Gate_Sync(channel,gate_async);
		} else {
			return SyntaxError;
		}
		break;

	case query_simple:
		if (globals.ChannelState[channel].gate_type==gate_sync) {
			return query_string(response, "SYNC");
		} else {
			return query_string(response, "ASYNC");
		}
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_gate_level_67(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_gate_level)) {
		return status;
	}
	if (globals.Flash.is_func_gen[channel]) {
		return Unrecognized;
	}

	switch (command_type) {
	case command_withparam:
		if (!strcmp(parameter,"hi") || !strcmp(parameter,"high")) {
			return Set_Gate_Level(channel,gate_high);
		} else if (!strcmp(parameter,"low") || !strcmp(parameter,"lo")) {
			return Set_Gate_Level(channel,gate_low);
		} else {
			return SyntaxError;
		}
		break;

	case query_simple:
		if (globals.ChannelState[channel].gate_level==gate_high) {
			return query_string(response, "HI");
		} else {
			return query_string(response, "LO");
		}
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_delay_test58(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int on_off, status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_delay)) {
		return status;
	}

	switch (command_type) {
	case command_withparam:
		if (status=process_on_off (parameter, &on_off)) {
			return status;
		}
		globals.ChannelState[channel].test_delay_mode=on_off;
		Set_Mux(channel);
		return OK;
		break;

	default:
		return IllegalParameter;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_wai_10(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	/* the *WAI command has no effect since all OP1B commands are non-overlapping */

	switch (command_type) {
	case command_simple:
		return OK;
		break;

	default:

		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_opc_5(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	/* the OPC commands automatically signal "operation complete" */
	/* since all OP1B commands are non-overlapping */

	switch (command_type) {
	case command_simple:
		GPIB_set_ESR(0x01,1);
		return OK;
		break;

	case query_simple:
		return query_int (response, 1);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_ese_2(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int value, status;

	switch (command_type) {
	case command_withparam:
		if (status = process_int_range (parameter, &value, 0, 255)) {
			return status;
		}
		GPIB_set_ESE(0xff,0);
		GPIB_set_ESE(value,1);
		return OK;
		break;

	case query_simple:
		return query_int (response, GPIB_get_ESE());
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_esr_3(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int orig_esr;

	switch (command_type) {
	case query_simple:
		orig_esr =  GPIB_get_ESR();
		GPIB_clear_events();
		return query_int (response, orig_esr);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_cls_1(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	switch (command_type) {
	case command_simple:
		GPIB_clear_events();
		globals.Errors.number_of_errors=0;
		return OK;
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_sre_7(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int value, status;

	switch (command_type) {
	case command_withparam:
		if (status = process_int_range (parameter, &value, 0, 255)) {
			return status;
		}
		GPIB_set_SRE(0xbf,0);
		GPIB_set_SRE(value,1);
		return OK;
		break;

	case query_simple:
		return query_int (response, GPIB_get_SRE());
		break;

	default:
		return SyntaxError;
		break;
	}
}


static int Go_stb_8(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	switch (command_type) {
	case query_simple:
		return query_int (response, GPIB_and_VXI_get_STB());
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_tst_9(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	switch (command_type) {
	case query_simple:
		return query_int (response, 0);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_syst_ver_12(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	switch (command_type) {
	case query_simple:
		return query_string(response, SCPI_version);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_event_13(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	switch (command_type) {
	case query_simple:
		return query_int (response, 0);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_oper_enable15(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int value, status;

	switch (command_type) {
	case command_withparam:
		if (status = process_int_range (parameter, &value, 0, 255)) {
			return status;
		}
		globals.Registers.oper_enable_register=value;
		return OK;
		break;

	case query_simple:
		return query_int (response, globals.Registers.oper_enable_register);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_ques_enable18(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int value, status;

	switch (command_type) {
	case command_withparam:
		if (status = process_int_range (parameter, &value, 0, 255)) {
			return status;
		}
		globals.Registers.ques_enable_register=value;
		return OK;
		break;

	case query_simple:
		return query_int (response, globals.Registers.ques_enable_register);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_preset_19(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	switch (command_type) {
	case command_simple:
		globals.Registers.oper_enable_register=0;
		globals.Registers.ques_enable_register=0;
		return OK;
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_zout_20(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int value, status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_zout)) {
		return status;
	}
	if (!globals.Flash.switchable_zout[channel] || globals.Flash.volt_ctrl_pw[channel]) {
		return Unrecognized;
	}

	switch (command_type) {
	case command_param_units:
		// non-std unit handling, because zout is an integer, not a float
		if (strcmp(units,"ohm")) {
			return UnknownUnits;
		}
		/* no break */

	case command_withparam:
		if (status=process_two_ints (parameter, &value, globals.Flash.zout_min[channel], globals.Constraints.err_max_zout[channel])) {
			return status;
		}
		return Set_zout(channel,value,1);
		break;

	case query_simple:
		return query_int (response, globals.ChannelState[channel].zout);
		break;

	case query_param:
		return query_min_max_int(response, parameter, globals.Flash.zout_min[channel], globals.Constraints.err_max_zout[channel]);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_prot_trip_21(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	switch (command_type) {
	case query_simple:
		if (I2C_Read(PCF8574A+Button_Press_Port) & Overload_Input) {
			return query_int (response, 0);    /* overload not tripped */
		} else {
			return query_int (response, 1);    /* overload tripped */
		}
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_gpib_addr_59(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int value, status;

	switch (command_type) {
	case command_withparam:
		if (status = process_int_range (parameter, &value, 0, 30)) {
			return status;
		}
		GPIB_change_address(value);
		return OK;
		break;

	case query_simple:
		return query_int (response, globals.Flash.gpib_address);
		break;

	case query_param:
		return query_min_max_int (response, parameter, 0, 30);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_ser_baud_60(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int new_baud, status;
	int valid_choices[] = {1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200};

	switch (command_type) {
	case command_withparam:
		if (status = process_int_param (parameter, &new_baud, 8, valid_choices, NO_ON_OFF)) {
			return status;
		}
		return IO_Setup_RS232(new_baud, globals.Flash.hardhand);
		break;

	case query_simple:
		return query_int (response, globals.Flash.baud);
		break;

	case query_param:
		return query_min_max_int (response, parameter, 1200, 115200);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_ser_rts_64(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	char new_hardhand;

	switch (command_type) {
	case command_withparam:
		if (!strcmp(parameter,"rfr") || !strcmp(parameter,"ibf")
		                || !strcmp(parameter,"ibfull")) {
			// these are valid hardware handshake modes
			new_hardhand = 1;
		} else if (!strcmp(parameter,"on")) {
			new_hardhand = 0;
		} else {
			return IllegalParameter;
		}

		return IO_Setup_RS232(globals.Flash.baud, new_hardhand);
		break;

	case query_simple:
		if (globals.Flash.hardhand) {
			return query_string(response, "IBF");
		} else {
			return query_string(response, "ON");
		}
		return OK;
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_load_68(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	float new_load_type;
	int status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_load_type)) {
		return status;
	}
	if (!globals.Flash.switchable_load[channel]) {
		return Unrecognized;
	}

	new_load_type=1.0;

	switch (command_type) {
	case command_param_units:
		if (status=Handle_Units(&new_load_type,units,"ohm")) {
			return status;
		}
		/* no break */

	case command_withparam:
		if (status = process_float_param (parameter, &new_load_type, globals.Constraints.err_min_load_type[channel], globals.Constraints.err_max_load_type[channel], NORMAL_ZERO)) {
			return status;
		}
		return Set_Load(channel,new_load_type);
		break;

	case query_simple:
		return query_float(response, globals.ChannelState[channel].load_type);
		break;

	case query_param:
		return query_min_max_float (response, parameter, globals.Constraints.err_min_load_type[channel], globals.Constraints.err_max_load_type[channel]);
		break;

	default:

		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_meas_ampl_69(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_amplitude)) {
		return status;
	}
	if (!globals.Flash.monitor_enabled[channel]) {
		return Unrecognized;
	}

	switch (command_type) {
	case query_simple:
		return query_float(response, globals.ChannelState[channel].Curr_Mon_value);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_rst_6(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	switch (command_type) {
	case command_simple:
		Main_Rst();
		return OK;
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_calib_amp_72(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	float cal_val;
	int status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_amplitude)) {
		return status;
	}
	if (!globals.Flash.voltage_enabled[channel] && !globals.Flash.current_enabled[channel]) {
		return Unrecognized;
	}

	cal_val=1.0;

	switch (command_type) {
	case command_param_units:
		if (globals.Flash.current_enabled[channel]) {
			if (status=Handle_Units(&cal_val,units,"a")) {
				return status;
			}
		} else if (globals.Flash.voltage_enabled[channel]) {
			if (status=Handle_Units(&cal_val,units,"v")) {
				return status;
			}
			/* no break */
		}

	case command_withparam:
		if (!String_is_it_numeric(parameter)) {
			return SyntaxError;
		}

		return Set_Amp_Calib(channel,atof(parameter)*cal_val);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_calib_mon_73(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	float mon_val;
	int status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_amplitude)) {
		return status;
	}
	if (!globals.Flash.monitor_enabled[channel]) {
		return Unrecognized;
	}

	mon_val=1.0;

	switch (command_type) {
	case command_param_units:
		if (status=Handle_Units(&mon_val,units,"a")) {
			return status;
		}

	case command_withparam:
		if (!String_is_it_numeric(parameter)) {
			return SyntaxError;
		}

		return Set_Mon_Calib(channel,atof(parameter)*mon_val);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_mon_step_74(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	float mon_val;
	float span , step_min, step_max;
	int status;
	int eprom_loc;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_amplitude)) {
		return status;
	}
	if (!globals.Flash.monitor_enabled[channel]) {
		return Unrecognized;
	}

	mon_val=1.0;

	span = fabs(globals.Flash.max_ampl[channel]-globals.Flash.min_ampl[channel]);
	if (globals.Flash.voltage_enabled[channel] || globals.Flash.current_enabled[channel]) {
		step_min = span / 5000.0;
		step_max = span / 5.0;
	} else {
		step_min = 0.0001;
		step_max = 10.0;
	}

	switch (command_type) {
	case command_param_units:
		if (status=Handle_Units(&mon_val,units,"a")) {
			return status;
		}

	case command_withparam:
		if (status = process_float_param (parameter, &mon_val, step_min, step_max, NORMAL_ZERO)) {
			return status;
		}
		mon_val=fabs(mon_val);

		if ((mon_val < step_min) || (mon_val > step_max)) {
			return OutOfRange;
		}

		globals.Flash.monitor_step[channel]=mon_val;
		eprom_loc = (char *) &(globals.Flash.monitor_step) - (char *) &(globals.Flash.flash_start);
		writeUserBlock(&globals.Flash, eprom_loc, sizeof(globals.Flash.monitor_step));
		break;

	case query_simple:
		return query_float(response, globals.Flash.monitor_step[channel]);
		break;

	case query_param:
		return query_min_max_float (response, parameter, step_min, step_max);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_outputtype_75(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int new_logic_level, status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_logic_level)) {
		return status;
	}
	if (!globals.Flash.logic_level_enabled) {
		return Unrecognized;
	}

	switch (command_type) {
	case command_withparam:
		if (!strcmp(parameter,"ttl")) {
			new_logic_level=logic_ttl;
		} else if (!strcmp(parameter,"ecl")) {
			new_logic_level=logic_ecl;
		} else {
			return SyntaxError;
		}

		return Set_Logic_Level(channel,new_logic_level);
		break;

	case query_simple:
		if (globals.ChannelState[channel].logic_level==logic_ttl) {
			return query_string(response, "TTL");
		} else {
			return query_string(response, "ECL");
		}
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}



static int Go_calib_os_76(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	float mon_val;
	int status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_offset)) {
		return status;
	}
	if ( !globals.Flash.current_offset_enabled[channel] && !globals.Flash.voltage_offset_enabled[channel]) {
		return Unrecognized;
	}

	mon_val=1.0;

	switch (command_type) {
	case command_param_units:
		if (globals.Flash.current_offset_enabled[channel]) {
			if (status=Handle_Units(&mon_val,units,"a")) {
				return status;
			}
		} else {
			if (status=Handle_Units(&mon_val,units,"v")) {
				return status;
			}
		}

	case command_withparam:
		if (!String_is_it_numeric(parameter)) {
			return SyntaxError;
		}

		return Set_OS_Calib(channel,atof(parameter)*mon_val);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_calib_pw_77(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	float pw_adjust;
	int status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_pw)) {
		return status;
	}

	pw_adjust=1.0;

	switch (command_type) {
	case command_param_units:
		if (status=Handle_Units(&pw_adjust,units,"s")) {
			return status;
		}
		/* no break */

	case command_withparam:
		if (status = process_float_param (parameter, &pw_adjust, -1.0e-6, 1.0e-6, NORMAL_ZERO)) {
			return status;
		}
		return Set_PW_shift(channel,pw_adjust);
		break;

	case query_simple:
		return query_float(response, Get_PW_shift(channel));
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_routeclose_78(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int error_num;
	int temp1, temp2, status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_route)) {
		return status;
	}
	if (!globals.Flash.routing_required[channel]) {
		return Unrecognized;
	}

	temp1 = globals.ChannelState[channel].route_primary;
	temp2 = globals.ChannelState[channel].route_secondary;

	switch (command_type) {
	case command_withparam:
		if (error_num=Parse_chan_list(channel,
		                              parameter,
		                              &temp1,
		                              &temp2,
		                              NULL)) {
			return error_num;
		} else {
			Set_Route(channel,ROUTE_PRIMARY,temp1);
			Set_Route(channel,ROUTE_SECONDARY,temp2);
			return OK;
		}
		break;

	case query_param:
		if (error_num=Parse_chan_list(channel,
		                              parameter,
		                              &temp1,
		                              &temp2,
		                              response)) {
			return error_num;
		} else {
			return OK;
		}
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Parse_chan_list(int channel,char *parameter,int *primary_selected, int *secondary_selected, gchar** response)
{
	int i;
	int n;
	int pointer;
	int has_module_name;
	int *value_pointer;

#define PARSE_MAX_STRING 20


	if ( !(parameter[0]=='(' && parameter[1]=='@')) {
		return SyntaxError;
	}

	if (strchr (parameter, ':')) {
		return Route_Range_Error;
	}

	if (strchr (parameter, '!')) {
		return Route_Range_Error;
	}


	pointer=1;

	do {
		int error_num = OK;

		pointer++;
		has_module_name = FALSE;

		/* get module name, if any */

		GString *name = g_string_new ("");

		for (i=0; isalpha(parameter[pointer]) && (i<PARSE_MAX_STRING); i++) {
			name = g_string_append_c (name, parameter[pointer]);
			pointer++;
		}

		value_pointer = primary_selected;
		if (i>0) {
			has_module_name = TRUE;

			if (!strcmp (name->str, "anod")) {
				value_pointer = primary_selected;
			} else if (!strcmp (name->str, "cath")) {
				if (globals.Flash.routing_required[channel]<2) {
					error_num = IllegalParameter;
				}
				value_pointer = secondary_selected;
			} else {
				error_num = IllegalParameter;
			}

			if (!error_num && (parameter[pointer] == '(' )) {
				pointer++;
			} else {
				error_num =SyntaxError;
			}

		}

		g_string_free (name, TRUE);

		if (error_num) {
			return error_num;
		}

		GString *digits = g_string_new ("");

		/* get digits */
		for (i=0; isdigit(parameter[pointer]) && (i<PARSE_MAX_STRING); i++) {
			digits = g_string_append_c (digits, parameter[pointer]);
			pointer++;
		}

		if (i==0) {
			error_num = SyntaxError;
		}

		n = atoi(digits->str);
		g_string_free (digits, TRUE);

		if (error_num) {
			return error_num;
		}

		if ((n < 1) || (n > globals.Flash.routing_max_pins[channel])) {
			return OutOfRange;
		}

		if (has_module_name) {
			if (parameter[pointer] == ')' ) {
				pointer++;
			} else {
				return SyntaxError;
			}
		}

		/* query or command? */
		if (response) {
			if (*value_pointer == n) {
				*response = g_strdup ("1 ");
			} else {
				*response = g_strdup ("0 ");
			}
		} else {
			if (value_pointer) {
				*value_pointer=n;
			}
		}


	} while (parameter[pointer]==',');

	if ( parameter[pointer]==')') {
		pointer++;
		for(; parameter[pointer]; pointer++)
			if (!isspace(parameter[pointer])) {
				return SyntaxError;
			}
	} else {
		return SyntaxError;
	}

	return OK;
}


static int Go_dly_shift_82(gchar** response, int channel, char *parameter,char *units,int command_type)
{
#define num_of_dly_shift_points 2

	int value, status;
	float cal_point;
	float min_one_shot_delay;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_delay)) {
		return status;
	}

	switch (command_type) {
	case command_param_units:
		/* if param=point number, and units=measurement, then update calibration */
		if (String_is_it_pos_int(parameter) && String_is_it_numeric(units)) {
			value=atoi(parameter);
			if (value>num_of_dly_shift_points || value<1) {
				return IllegalParameter;
			}
			cal_point=atof(units);
			return Set_Dly_Shr_Cal(channel,value,cal_point);
		} else if (String_is_it_pos_int(parameter) && !strcmp(units,"go")) {
			value=atoi(parameter);
			if (value>num_of_dly_shift_points || value<1) {
				return IllegalParameter;
			}
			return Set_Dly_Shr_Nom(channel,value);
		} else {
			return SyntaxError;
		}

		return OK;
		break;

	case query_param:
		return query_min_max_int(response, parameter, 1, num_of_dly_shift_points);
		break;

	case query_simple:

		min_one_shot_delay = globals.Flash.delay_pwl[channel][0][0][0];
		
		*response = g_strdup_printf (
			"Fixed delay: %f ns, PG-SYNC propagation delay: %f ns, narrowest variable delay: %f ns, all delays valid: %s, delay monotonic in external trigger mode: %s", 
			globals.Flash.delay_shrink[channel]*1e9, 
			globals.Flash.propagation_delay[channel]*1e9, 
			globals.Flash.delay_pwl[channel][0][0][0]*1e9,
			(globals.Flash.delay_shrink[channel] >= min_one_shot_delay) ? "TRUE" : "FALSE",
			(( globals.Flash.delay_shrink[channel] - globals.Flash.propagation_delay[channel] ) >= min_one_shot_delay) ? "TRUE" : "FALSE");
		return OK;
		break; 

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_amp_pnt_83(gchar** response, int channel, char *parameter,char *units,int command_type,int cal_type)
{
	int value,status;
	float cal_point;

	switch (cal_type) {
	case pwl_burst_values:
		if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_Burst_Time)) {
			return status;
		}
		if (globals.Flash.max_burst_count[channel]<2) {
			return Unrecognized;
		}
		break;
	case pwl_ampl_values:
		if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_amplitude)) {
			return status;
		}
		if (!globals.Flash.voltage_enabled[channel] && !globals.Flash.current_enabled[channel]) {
			return Unrecognized;
		}
		break;
	case pwl_distort_values:
		if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_amplitude)) {
			return status;
		}
		if (!globals.Flash.distort_enabled[channel]) {
			return Unrecognized;
		}
		break;

	case pwl_rise_time_values:
		if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_rise_time)) {
			return status;
		}
		if (globals.Flash.fixed_rise_time[channel]) {
			return Unrecognized;
		}
		break;
	case pwl_slew_values:
		if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_slew)) {
			return status;
		}
		if (!globals.Flash.curr_slew[channel]) {
			return Unrecognized;
		}
		break;
	case pwl_os_values:
		if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_offset)) {
			return status;
		}
		if (!globals.Flash.voltage_offset_enabled[channel] && !globals.Flash.current_offset_enabled[channel]) {
			return Unrecognized;
		}
		break;
	case pwl_pw_values:
		if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_pw)) {
			return status;
		}
		break;
	case pwl_delay_values:
		if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_delay)) {
			return status;
		}
		break;
	case pwl_period_values:
		if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_frequency)) {
			return status;
		}
		break;
	}

	switch (command_type) {
	case command_param_units:
		/* if param=point number, and units=measurement, then update calibration */
		if (String_is_it_pos_int(parameter) && String_is_it_numeric(units)) {
			value=atoi(parameter);
			if (value>Get_VI_Num_Pnts(cal_type,channel) || value<1) {
				return IllegalParameter;
			}
			cal_point=atof(units);
			return Set_VI_Cal_Pnt(cal_type,channel,value,cal_point);
		} else if (String_is_it_pos_int(parameter) && !strcmp(units,"go")) {
			value=atoi(parameter);
			if (value>Get_VI_Num_Pnts(cal_type,channel) || value<1) {
				return IllegalParameter;
			}
			if (status=Set_Cal_Nom(channel,value,cal_type,NULL)) {
				return status;
			}
		} else if (String_is_it_pos_int(parameter) && !strcmp(units,"delete")) {
			value=atoi(parameter);
			if (value>Get_VI_Num_Pnts(cal_type,channel) || value<1) {
				return IllegalParameter;
			}
			if (status=Set_VI_Del_Cal(cal_type,channel,value)) {
				return status;
			}
		} else if (String_is_it_numeric(parameter) && !strcmp(units,"add")) {
			cal_point=atof(parameter);
			if (status=Set_VI_Add_Cal(cal_type,channel,cal_point)) {
				return status;
			}
		} else {
			return SyntaxError;
		}

		return OK;
		break;

	case query_param:
		return query_min_max_int(response, parameter, 1, Get_VI_Num_Pnts(cal_type,channel));
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


int Handle_Curr_Slew_Unit(float *new_val,char *units);
int Handle_Curr_Slew_Unit(float *new_val,char *units)
{
	char *slash;
	float tmp1, tmp2;

	*new_val = 1.0;

	slash = strstr (units,"/");
	if (slash == NULL) {
		return UnknownUnits;
	}

	slash[0]=0;

	if (Handle_Units (&tmp1, units, "a") != OK) {
		return UnknownUnits;
	}

	if (Handle_Units (&tmp2, slash+1, "s") != OK) {
		return UnknownUnits;
	}

	*new_val = tmp1 / tmp2;

	return OK;
}


static int Go_puls_count_88(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int value, status;
	int min_val;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_Burst_Count)) {
		return status;
	}

	/* if the maximum burst count is 0 or 1, disable this command */
	if (globals.Flash.max_burst_count[channel]<2) {
		return Unrecognized;
	}

	min_val = 1;                         	// -BR
	if (globals.Flash.burst_func[channel]) {
		min_val = 0;    // -PANB
	}

	switch (command_type) {
	case command_withparam:
		if (status = process_int_range (parameter, &value, min_val, globals.Constraints.err_max_burst_count[channel])) {
			return status;
		}
		return Set_Burst_Count(channel,value,globals.ChannelState[channel].burst_time);
		break;

	case query_simple:
		return query_int (response, globals.ChannelState[channel].burst_count);
		break;

	case query_param:
		return query_min_max_int(response, parameter, min_val, globals.Constraints.err_max_burst_count[channel]);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_puls_sep_89(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	float new_pw;
	int status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_Burst_Time)) {
		return status;
	}

	/* if the maximum burst count is 0 or 1, disable this command */
	if ((globals.Flash.max_burst_count[channel]<2) || (globals.Flash.burst_func[channel])) {
		return Unrecognized;
	}

	new_pw=1.0;

	switch (command_type) {
	case command_param_units:
		if (status=Handle_Units(&new_pw,units,"s")) {
			return status;
		}
		/* no break */

	case command_withparam:
		globals.ChannelState[channel].pw_ctrl_mode=pw_normal;
		if (status = process_float_param (parameter, &new_pw, globals.Constraints.err_min_burst_time[channel], globals.Constraints.err_max_burst_time[channel], NORMAL_ZERO)) {
			return status;
		}
		return Set_Burst_Time(0,0,0,channel,new_pw);
		break;

	case query_simple:
		return query_float(response, globals.ChannelState[channel].burst_time);
		break;

	case query_param:
		return query_min_max_float (response, parameter, globals.Constraints.err_min_burst_time[channel], globals.Constraints.err_max_burst_time[channel]);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_sys_pwd_92(gchar** response, int channel, char *parameter,int command_type)
{
	gchar *old_password = NULL;
	gchar *new_password = NULL;
	char *new_loc;
	int error_num;

	switch (command_type) {
	case command_withparam:
		/* new password follows comma */

		new_loc = strchr(parameter,',');
		if (new_loc == NULL) {
			return password_change_error;
		}

		new_password = g_strdup_printf ("%s", new_loc + 1);
		new_loc[0]=0;
		old_password = g_strdup (parameter);

		error_num = OK;
		if ((strlen(new_password)< 6) || (strlen(new_password)>32)) {
			error_num = password_change_error;
		}

		if (!error_num) {
			error_num = change_password (old_password, new_password);
		}

		g_free (new_password);
		g_free (old_password);
		return error_num;

	default:
		return SyntaxError;
		break;
	}
}


static int Go_eprom_sus_93(gchar** response, int channel, char *parameter,int command_type)
{
	if (channel) {
		return InvalidChannel;
	}

	switch (command_type) {
	case command_withparam:
		if (!strcmp(parameter,"1")) {
			globals.Flags.flash_writes_suspended=1;
		} else if (!strcmp(parameter,"0")) {
			globals.Flags.flash_writes_suspended=0;
			writeUserBlock(&globals.Flash,0,sizeof(globals.Flash));
		} else {
			return SyntaxError;
		}

		Menu_Clear_Buttons(YES);
		return OK;
		break;

	case query_simple:
		return query_int (response, globals.Flags.flash_writes_suspended);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_eprom_reset_102(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int status, value;

	if (channel) {
		return InvalidChannel;
	}

	switch (command_type) {
	case command_withparam:
		if (status = process_int_range (parameter, &value, 0, sizeof(globals.Flash)-1)) {
			return status;
		}
		initFlash(&globals.Flash, TRUE, value);
		Main_Rst();
		return OK;
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_rise_time_94(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	float new_rise_time;
	int status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_rise_time)) {
		return status;
	}
	if (globals.Flash.fixed_rise_time[channel]) {
		return Unrecognized;
	}

	new_rise_time=1.0;

	switch (command_type) {
	case command_param_units:
		if (status=Handle_Units(&new_rise_time,units,"s")) {
			return status;
		}
		/* no break */

	case command_withparam:
		if (status = process_float_param (parameter, &new_rise_time, globals.Constraints.err_min_rise_time[channel], globals.Constraints.err_max_rise_time[channel], NORMAL_ZERO)) {
			return status;
		}
		return Set_rise_time(0,0,0,channel,new_rise_time);
		break;

	case query_simple:
		return query_float(response, globals.ChannelState[channel].rise_time);
		break;

	case query_param:
		return query_min_max_float (response, parameter, globals.Constraints.err_min_rise_time[channel], globals.Constraints.err_max_rise_time[channel]);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_rcl_53(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int value, status;

	switch (command_type) {
	case command_withparam:
		if (status = process_int_range (parameter, &value, 0, 3)) {
			return status;
		}
		Set_Rcl(value);
		return OK;
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_sav_54(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int value, status;

	switch (command_type) {
	case command_withparam:
		if (status = process_int_range (parameter, &value, 0, 3)) {
			return status;
		}
		Set_Sav(value);
		return OK;
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_soft_current_limit_96(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	float new_soft_current_limit;
	int status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_current_limit)) {
		return status;
	}
	if (!globals.Flash.soft_current_limit_enabled[channel]) {
		return Unrecognized;
	}

	new_soft_current_limit=1.0;

	switch (command_type) {
	case command_param_units:
		if (status=Handle_Units(&new_soft_current_limit,units,"a")) {
			return status;
		}
		/* no break */

	case command_withparam:
		if (status = process_float_param (parameter, &new_soft_current_limit, globals.Constraints.err_min_soft_current_limit[channel], globals.Constraints.err_max_soft_current_limit[channel], NORMAL_ZERO)) {
			return status;
		}

		return Set_current_limit(0,channel,new_soft_current_limit);

		break;

	case query_simple:
		return query_float(response, globals.ChannelState[channel].soft_current_limit);
		break;

	case query_param:
		return query_min_max_float (response, parameter, globals.Constraints.err_min_soft_current_limit[channel], globals.Constraints.err_max_soft_current_limit[channel]);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_curr_slew_98(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	float new_slew;
	int status;

	if (status = check_channel_ok (channel, globals.Flash.channels, globals.Flash.ChanKey_slew)) {
		return status;
	}
	if (!globals.Flash.curr_slew[channel]) {
		return Unrecognized;
	}

	new_slew=1.0;

	switch (command_type) {
	case command_param_units:
		if (status=Handle_Curr_Slew_Unit(&new_slew,units)) {
			return status;
		}
		/* no break */

	case command_withparam:
		if (status = process_float_param (parameter, &new_slew, globals.Constraints.err_min_slew[channel], globals.Constraints.err_max_slew[channel], NORMAL_ZERO)) {
			return status;
		}
		return Set_slew(0,0,0,channel,new_slew);
		break;

	case query_simple:
		return query_float(response, globals.ChannelState[channel].slew);
		break;

	case query_param:
		return query_min_max_float (response, parameter, globals.Constraints.err_min_slew[channel], globals.Constraints.err_max_slew[channel]);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_cal_100(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int no_report, status;
	CalStruct caldata;

	if (!globals.Flash.self_cal) {
		return Unrecognized;
	}

	no_report = 0;

	switch (command_type) {
	case command_simple:
		no_report = 1;
		// continue below

	case query_simple:
		status = do_full_self_cal(&caldata);
		if (!no_report) {
			query_string(response, caldata.response->str);
			g_string_free (caldata.response, TRUE);
		}
		return status;
		break;

	default:
		return SyntaxError;
		break;
	}
}


static int Go_cal_interval_101(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int eprom_loc, status, the_number;

	if (!globals.Flash.self_cal) {
		return Unrecognized;
	}

	switch (command_type) {
	case command_withparam:
		if (status = process_int_range (parameter, &the_number, 0, 365)) {
			return status;
		}

		globals.Flash.self_cal_interval = the_number;
		eprom_loc = (char *) &(globals.Flash.self_cal_interval) - (char *) &(globals.Flash.flash_start);
		writeUserBlock(&globals.Flash, eprom_loc, sizeof(globals.Flash.self_cal_interval));
		return OK;
		break;

	case query_simple:
		return query_int (response, globals.Flash.self_cal_interval);
		break;

	case query_param:
		return query_min_max_int(response, parameter, 0, 365);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_atten_103(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int on_off, status;

	switch (command_type) {
	case command_withparam:
		if (status=process_on_off (parameter, &on_off)) {
			return status;
		}
		globals.Flags.attenuators_enabled = on_off;

		return OK;
		break;

	case query_simple:
		return query_int (response, globals.Flags.attenuators_enabled);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_eprom_resize_105(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	/* copies data from old ten-point-ranges into new-style (May 2018) 32-point ranges */

	int i, j, k, l;

	if (channel) {
		return InvalidChannel;
	}

	switch (command_type) {
	case command_simple:

		for (i=0;i<max_channels;i++) {
			for (l=0;l<old_range_size_ten;l++) {

				for (j=0;j<ampl_ranges;j++) {
					for (k=0;k<ampl_polarities;k++) {
						globals.Flash.ampl_dacval[i][j][k][l] = globals.Flash.obs_ampl_dacval[i][j][k][l];
						globals.Flash.ampl_pwl[i][j][k][l] = globals.Flash.obs_ampl_pwl[i][j][k][l];
						globals.Flash.distort_dacval[i][j][k][l] = globals.Flash.obs_distort_dacval[i][j][k][l];
						globals.Flash.rise_time_dacval[i][j][k][l] = globals.Flash.obs_rise_time_dacval[i][j][k][l];
						globals.Flash.rise_time_pwl[i][j][k][l] = globals.Flash.obs_rise_time_pwl[i][j][k][l];
					}
				}

				for (j=0;j<os_ranges;j++) {
					for (k=0;k<os_polarities;k++) {
						globals.Flash.os_dacval[i][j][k][l] = globals.Flash.obs_os_dacval[i][j][k][l];
						globals.Flash.os_pwl[i][j][k][l] = globals.Flash.obs_os_pwl[i][j][k][l];
					}
				}

				for (j=0;j<load_type_ranges;j++) {
					for (k=0;k<load_type_polarities;k++) {
						globals.Flash.load_type_dacval[i][j][k][l] = globals.Flash.obs_load_type_dacval[i][j][k][l];
						globals.Flash.load_type_pwl[i][j][k][l] = globals.Flash.obs_load_type_pwl[i][j][k][l];
					}
				}

				for (j=0;j<timing_ranges;j++) {
					for (k=0;k<timing_polarities;k++) {
						globals.Flash.pw_dacval[i][j][k][l] = globals.Flash.obs_pw_dacval[i][j][k][l];
						globals.Flash.pw_pwl[i][j][k][l] = globals.Flash.obs_pw_pwl[i][j][k][l];
						globals.Flash.delay_dacval[i][j][k][l] = globals.Flash.obs_delay_dacval[i][j][k][l];
						globals.Flash.delay_pwl[i][j][k][l] = globals.Flash.obs_delay_pwl[i][j][k][l];
						globals.Flash.period_dacval[i][j][k][l] = globals.Flash.obs_period_dacval[i][j][k][l];
						globals.Flash.period_pwl[i][j][k][l] = globals.Flash.obs_period_pwl[i][j][k][l];
						globals.Flash.burst_dacval[i][j][k][l] = globals.Flash.obs_burst_dacval[i][j][k][l];
						globals.Flash.burst_pwl[i][j][k][l] = globals.Flash.obs_burst_pwl[i][j][k][l];
						globals.Flash.slew_dacval[i][j][k][l] = globals.Flash.obs_slew_dacval[i][j][k][l];
						globals.Flash.slew_pwl[i][j][k][l] = globals.Flash.obs_slew_pwl[i][j][k][l];
					}
				}

			}

			for (l=old_range_size_ten;l<std_range_size;l++) {

				for (j=0;j<ampl_ranges;j++) {
					for (k=0;k<ampl_polarities;k++) {
						globals.Flash.ampl_dacval[i][j][k][l] = 0;
						globals.Flash.ampl_pwl[i][j][k][l] = 0;
						globals.Flash.distort_dacval[i][j][k][l] = 0;
						globals.Flash.rise_time_dacval[i][j][k][l] = 0;
						globals.Flash.rise_time_pwl[i][j][k][l] = 0;
					}
				}

				for (j=0;j<os_ranges;j++) {
					for (k=0;k<os_polarities;k++) {
						globals.Flash.os_dacval[i][j][k][l] = 0;
						globals.Flash.os_pwl[i][j][k][l] = 0;
					}
				}

				for (j=0;j<load_type_ranges;j++) {
					for (k=0;k<load_type_polarities;k++) {
						globals.Flash.load_type_dacval[i][j][k][l] = 0;
						globals.Flash.load_type_pwl[i][j][k][l] = 0;
					}
				}

				for (j=0;j<timing_ranges;j++) {
					for (k=0;k<timing_polarities;k++) {
						globals.Flash.pw_dacval[i][j][k][l] = 0;
						globals.Flash.pw_pwl[i][j][k][l] = 0;
						globals.Flash.delay_dacval[i][j][k][l] = 0;
						globals.Flash.delay_pwl[i][j][k][l] = 0;
						globals.Flash.period_dacval[i][j][k][l] = 0;
						globals.Flash.period_pwl[i][j][k][l] = 0;
						globals.Flash.burst_dacval[i][j][k][l] = 0;
						globals.Flash.burst_pwl[i][j][k][l] = 0;
						globals.Flash.slew_dacval[i][j][k][l] = 0;
						globals.Flash.slew_pwl[i][j][k][l] = 0;
					}
				}
			}
		}

		writeUserBlock(&globals.Flash,0,sizeof(globals.Flash));

		Main_Rst();
		return OK;
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_eprom_resize_ampl_106(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	/* copies data from old ten-point-ranges into new-style (May 2018) 32-point ranges */

	int i, j, k, l;

	if (channel) {
		return InvalidChannel;
	}

	switch (command_type) {
	case command_simple:

		for (i=0;i<max_channels;i++) {
			for (l=0;l<old_range_size_ten;l++) {
				for (j=0;j<ampl_ranges;j++) {
					for (k=0;k<ampl_polarities;k++) {
						globals.Flash.ampl_dacval[i][j][k][l] = globals.Flash.obs_ampl_dacval[i][j][k][l];
						globals.Flash.ampl_pwl[i][j][k][l] = globals.Flash.obs_ampl_pwl[i][j][k][l];
					}
				}
			}

			for (l=old_range_size_ten;l<std_range_size;l++) {
				for (j=0;j<ampl_ranges;j++) {
					for (k=0;k<ampl_polarities;k++) {
						globals.Flash.ampl_dacval[i][j][k][l] = 0;
						globals.Flash.ampl_pwl[i][j][k][l] = 0;
					}
				}
			}
		}

		writeUserBlock(&globals.Flash,0,sizeof(globals.Flash));

		Main_Rst();
		return OK;
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_eprom_resize_offset_107(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	/* copies data from old ten-point-ranges into new-style (May 2018) 32-point ranges */

	int i, j, k, l;

	if (channel) {
		return InvalidChannel;
	}

	switch (command_type) {
	case command_simple:

		for (i=0;i<max_channels;i++) {
			for (l=0;l<old_range_size_ten;l++) {
				for (j=0;j<os_ranges;j++) {
					for (k=0;k<os_polarities;k++) {
						globals.Flash.os_dacval[i][j][k][l] = globals.Flash.obs_os_dacval[i][j][k][l];
						globals.Flash.os_pwl[i][j][k][l] = globals.Flash.obs_os_pwl[i][j][k][l];
					}
				}
			}

			for (l=old_range_size_ten;l<std_range_size;l++) {
				for (j=0;j<os_ranges;j++) {
					for (k=0;k<os_polarities;k++) {
						globals.Flash.os_dacval[i][j][k][l] = 0;
						globals.Flash.os_pwl[i][j][k][l] = 0;
					}
				}
			}
		}

		writeUserBlock(&globals.Flash,0,sizeof(globals.Flash));

		Main_Rst();
		return OK;
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}


static int Go_cal_checking_disable_108(gchar** response, int channel, char *parameter,char *units,int command_type)
{
	int on_off, status;

	switch (command_type) {
	case command_withparam:
		if (status=process_on_off (parameter, &on_off)) {
			return status;
		}
		globals.Sys.disable_timing_cal_percent_check = on_off;

		return OK;
		break;

	case query_simple:
		return query_int (response, globals.Sys.disable_timing_cal_percent_check);
		break;

	default:
		return SyntaxError;
		break;
	}

	return ThisShouldntHappen;
}