/* START LIBRARY DESCRIPTION ********************************************* PARSER.LIB Copyright (c) 1997, Avtech Electrosystems Ltd. DESCRIPTION: Parser functions. SUPPORT LIB'S: END DESCRIPTION **********************************************************/ #include "parser.h" #include //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 process_four_ints (char *parameter, int *value, int v1, int v2, int v3, int v4); 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 Go_freq_32_33(gchar** response, int channel, char *parameter,char *units,int command_type); 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 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,"*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 { 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 */ {13,68,71,72|optional,76}, /* syst:comm:ser:rec:bits - 62 */ {13,68,71,72|optional,77}, /* syst:comm:ser:rec:sbits - 63 */ {13,68,71,80,79}, /* syst:comm:ser:control:rts - 64 */ {13,68,71,72|optional,78}, /* syst:comm:ser:rec:echo - 65 */ {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 */ }; 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_posstr); } 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(¶meter,&units); 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 11: error_num=Go_syst_err_11(&response,channel,parameter,units,command_type); break; case 32: case 33: error_num=Go_freq_32_33(&response,channel,parameter,units,command_type); break; case 66: error_num=Go_syst_errcnt66(&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 { (*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 */ int Selected_Submenu=0, Submenu1_rem_loc=0, Type_Of_Menu=0, Submenu_On=0; if (!is_query && !(Selected_Submenu==Submenu1_rem_loc && Type_Of_Menu==Submenu_On)) { Menu_Update_Display(); } /* re-run error_check to update min/max values based on actual settings, not proposed settings */ Error_check(globals.ChannelState); // trigger a prompt if (interactive_terminal) { (*cbfunc)(user_data, ""); } g_free (in); } 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 && !globals.Flash.enable_avrq_extra_ampls) { return InvalidChannel; } if (*channel>5 && globals.Flash.enable_avrq_extra_ampls) { 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) { // this is a typical parser function - there will be many more added later 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, 1.0, 1.0e6, 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, 1.0, 1.0e6); break; default: return SyntaxError; break; } } 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)) { g_free (base); g_free (prefix); 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, i, 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_numeric(parameter)) { *value = atoi(parameter); 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_numeric(parameter)) { *value = atoi(parameter); if ((*valuemax_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 process_four_ints (char *parameter, int *value, int v1, int v2, int v3, int v4) { int valid_choices[4] = {v1, v2, v3, v4}; return process_int_param (parameter, value, 4, 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.number_of_errors==0) { get_error_text(response, OK); } else { get_error_text(response,globals.error_queue[1]); Error_Remove_From_Queue(); } return OK; break; default: return SyntaxError; break; } } 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.number_of_errors); break; default: return SyntaxError; break; } }