summaryrefslogtreecommitdiff
path: root/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'parser.c')
-rw-r--r--parser.c2022
1 files changed, 1011 insertions, 1011 deletions
diff --git a/parser.c b/parser.c
index d62d1f9..ea716be 100644
--- a/parser.c
+++ b/parser.c
@@ -1,1011 +1,1011 @@
-/* START LIBRARY DESCRIPTION *********************************************
-PARSER.LIB
- Copyright (c) 1997, Avtech Electrosystems Ltd.
-
-DESCRIPTION:
- Parser functions.
-
-SUPPORT LIB'S:
-END DESCRIPTION **********************************************************/
-
-
-#include "parser.h"
-#include <glib/gprintf.h>
-
-//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_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 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 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_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;
-}
-
-void Parser_main (char *raw_in, int interactive_terminal, void(*cbfunc)(gpointer, gchar *), gpointer user_data)
-{
- 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 */
- char current_command[max_input_word_length]; /* current command word being processed */
- int current_command_length; /* length of current command so far */
- 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;
-
- g_strstrip (raw_in);
-
- // add white space to the end of the input string - FIXME?
- gchar *in = g_strdup_printf ("%s ", raw_in);
-
- 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;
-
- while (isspace(in[in_pos]) || in[in_pos]==':' || in[in_pos]==';') {
- /* ignore leading spaces */
- ++in_pos;
- }
-
-
- /* 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;
- current_command_length = 0;
-
- 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 */
- current_command[current_command_length] = '\0';
-
- if (space_found) {
- /* Just end things if it is a semicolon */
- if (in[in_pos]!=';') {
- current_command[current_command_length] = in[in_pos];
- ++current_command_length;
- }
-
- current_command[current_command_length] = '\0';
- ++parameter_found;
- parameter = g_strdup (current_command);
- } else if (!space_found) {
- /* just a regular command word */
-
- /* terminate the current command string */
- current_command_length = 0; /* make room for a new command string */
- commands[command_depth]=Parser_id_word(current_command,&channel,&with_id_code);
-
- 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 */
- current_command[current_command_length] = in[in_pos];
- ++current_command_length;
- } /* 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 (!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:
- response = g_strdup_printf("routine_num: %d, channel: %d, parameter: %s, units: %s, command type: %d",routine_num,channel,parameter,units,command_type);
- 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:
- /* valid but not implemented yet */
- response = g_strdup_printf("routine_num: %d, channel: %d, parameter: %s, units: %s, command type: %d",routine_num,channel,parameter,units,command_type);
- 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);
-
- 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;
- char prefix[max_input_word_length];
- char base[max_input_word_length];
-
- strcpy (base, in_base);
-
- *mult=1.0;
- if (!strcmp(units,base)) {
- return OK;
- }
-
- // match base
- len_all = strlen (units);
- if (len_all == 0) {
- return OK;
- }
-
- len_base = strlen (base);
- pos = len_all - len_base;
-
- strcpy (prefix, units);
-
- if (!strcmp(base,"%") && (len_all >= 3) && !strcmp(prefix + len_all - 3,"pct")) {
- strcpy(base, "pct");
- prefix[len_all - 3] = 0;
- } else if (!strcmp(base,"pct") && !strcmp(prefix + len_all - 1,"%")) {
- strcpy(base, "%");
- prefix[len_all - 1] = 0;
- } else if (strcmp(prefix+pos,base)) {
- return UnknownUnits;
- } else {
- prefix[pos]=0;
- }
-
- if (strlen(prefix) == 0) {
- return OK;
- }
-
- // 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 {
- return UnknownUnits;
- }
-
- return OK;
-}
-
-
-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_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 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;
-}
-
-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;
- }
-}
-
+/* START LIBRARY DESCRIPTION *********************************************
+PARSER.LIB
+ Copyright (c) 1997, Avtech Electrosystems Ltd.
+
+DESCRIPTION:
+ Parser functions.
+
+SUPPORT LIB'S:
+END DESCRIPTION **********************************************************/
+
+
+#include "parser.h"
+#include <glib/gprintf.h>
+
+//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_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 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 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_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;
+}
+
+void Parser_main (char *raw_in, int interactive_terminal, void(*cbfunc)(gpointer, gchar *), gpointer user_data)
+{
+ 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 */
+ char current_command[max_input_word_length]; /* current command word being processed */
+ int current_command_length; /* length of current command so far */
+ 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;
+
+ g_strstrip (raw_in);
+
+ // add white space to the end of the input string - FIXME?
+ gchar *in = g_strdup_printf ("%s ", raw_in);
+
+ 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;
+
+ while (isspace(in[in_pos]) || in[in_pos]==':' || in[in_pos]==';') {
+ /* ignore leading spaces */
+ ++in_pos;
+ }
+
+
+ /* 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;
+ current_command_length = 0;
+
+ 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 */
+ current_command[current_command_length] = '\0';
+
+ if (space_found) {
+ /* Just end things if it is a semicolon */
+ if (in[in_pos]!=';') {
+ current_command[current_command_length] = in[in_pos];
+ ++current_command_length;
+ }
+
+ current_command[current_command_length] = '\0';
+ ++parameter_found;
+ parameter = g_strdup (current_command);
+ } else if (!space_found) {
+ /* just a regular command word */
+
+ /* terminate the current command string */
+ current_command_length = 0; /* make room for a new command string */
+ commands[command_depth]=Parser_id_word(current_command,&channel,&with_id_code);
+
+ 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 */
+ current_command[current_command_length] = in[in_pos];
+ ++current_command_length;
+ } /* 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 (!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:
+ response = g_strdup_printf("routine_num: %d, channel: %d, parameter: %s, units: %s, command type: %d",routine_num,channel,parameter,units,command_type);
+ 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:
+ /* valid but not implemented yet */
+ response = g_strdup_printf("routine_num: %d, channel: %d, parameter: %s, units: %s, command type: %d",routine_num,channel,parameter,units,command_type);
+ 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);
+
+ 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;
+ char prefix[max_input_word_length];
+ char base[max_input_word_length];
+
+ strcpy (base, in_base);
+
+ *mult=1.0;
+ if (!strcmp(units,base)) {
+ return OK;
+ }
+
+ // match base
+ len_all = strlen (units);
+ if (len_all == 0) {
+ return OK;
+ }
+
+ len_base = strlen (base);
+ pos = len_all - len_base;
+
+ strcpy (prefix, units);
+
+ if (!strcmp(base,"%") && (len_all >= 3) && !strcmp(prefix + len_all - 3,"pct")) {
+ strcpy(base, "pct");
+ prefix[len_all - 3] = 0;
+ } else if (!strcmp(base,"pct") && !strcmp(prefix + len_all - 1,"%")) {
+ strcpy(base, "%");
+ prefix[len_all - 1] = 0;
+ } else if (strcmp(prefix+pos,base)) {
+ return UnknownUnits;
+ } else {
+ prefix[pos]=0;
+ }
+
+ if (strlen(prefix) == 0) {
+ return OK;
+ }
+
+ // 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 {
+ return UnknownUnits;
+ }
+
+ return OK;
+}
+
+
+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_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 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;
+}
+
+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;
+ }
+}
+