/** * Read character parameter * @param context * @param value * @param len * @param mandatory * @return */ scpi_bool_t SCPI_ParamCharacters(scpi_t * context, const char ** value, size_t * len, scpi_bool_t mandatory) { scpi_bool_t result; scpi_parameter_t param; if (!value || !len) { SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); return FALSE; } result = SCPI_Parameter(context, ¶m, mandatory); if (result) { switch(param.type) { case SCPI_TOKEN_SINGLE_QUOTE_PROGRAM_DATA: case SCPI_TOKEN_DOUBLE_QUOTE_PROGRAM_DATA: *value = param.ptr + 1; *len = param.len - 2; break; default: *value = param.ptr; *len = param.len; break; } // TODO: return also parameter type (ProgramMnemonic, ArbitraryBlockProgramData, SingleQuoteProgramData, DoubleQuoteProgramData } return result; }
/** * Read BOOL parameter (0,1,ON,OFF) * @param context * @param value * @param mandatory * @return */ scpi_bool_t SCPI_ParamBool(scpi_t * context, scpi_bool_t * value, scpi_bool_t mandatory) { scpi_bool_t result; scpi_parameter_t param; int32_t intval; scpi_choice_def_t bool_options[] = { {"OFF", 0}, {"ON", 1}, SCPI_CHOICE_LIST_END /* termination of option list */ }; if (!value) { SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); return FALSE; } result = SCPI_Parameter(context, ¶m, mandatory); if (result) { if (param.type == SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA) { SCPI_ParamToInt32(context, ¶m, &intval); *value = intval ? TRUE : FALSE; } else { result = SCPI_ParamToChoice(context, ¶m, bool_options, &intval); if (result) { *value = intval ? TRUE : FALSE; } } } return result; }
/** * Read value from list of options * @param context * @param options * @param value * @param mandatory * @return */ scpi_bool_t SCPI_ParamChoice(scpi_t * context, const scpi_choice_def_t * options, int32_t * value, scpi_bool_t mandatory) { scpi_bool_t result; scpi_parameter_t param; if (!options || !value) { SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); return FALSE; } result = SCPI_Parameter(context, ¶m, mandatory); if (result) { result = SCPI_ParamToChoice(context, ¶m, options, value); } return result; }
/** * Read character parameter * @param context * @param value * @param len * @param mandatory * @return */ scpi_bool_t SCPI_ParamCharacters(scpi_t * context, const char ** value, size_t * len, scpi_bool_t mandatory) { scpi_bool_t result; scpi_parameter_t param; if (!value || !len) { SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); return FALSE; } result = SCPI_Parameter(context, ¶m, mandatory); if (result) { *value = param.ptr; *len = param.len; // TODO: return also parameter type (ProgramMnemonic, ArbitraryBlockProgramData, SingleQuoteProgramData, DoubleQuoteProgramData } return result; }
scpi_bool_t SCPI_ParamCopyText(scpi_t * context, char * buffer, size_t buffer_len, size_t * copy_len, scpi_bool_t mandatory) { scpi_bool_t result; scpi_parameter_t param; size_t i_from; size_t i_to; char quote; if (!buffer || !copy_len) { SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); return FALSE; } result = SCPI_Parameter(context, ¶m, mandatory); if (result) { switch (param.type) { case SCPI_TOKEN_SINGLE_QUOTE_PROGRAM_DATA: case SCPI_TOKEN_DOUBLE_QUOTE_PROGRAM_DATA: quote = param.type == SCPI_TOKEN_SINGLE_QUOTE_PROGRAM_DATA ? '\'' : '"'; for (i_from = 1, i_to = 0; i_from < (size_t) (param.len - 1); i_from++) { if (i_from >= buffer_len) { break; } buffer[i_to] = param.ptr[i_from]; i_to++; if (param.ptr[i_from] == quote) { i_from++; } } *copy_len = i_to; if (i_to < buffer_len) { buffer[i_to] = 0; } break; default: SCPI_ErrorPush(context, SCPI_ERROR_DATA_TYPE_ERROR); result = FALSE; } } return result; }
/** * Get arbitrary block program data and returns pointer to data * @param context * @param value result pointer to data * @param len result length of data * @param mandatory * @return */ scpi_bool_t SCPI_ParamArbitraryBlock(scpi_t * context, const char ** value, size_t * len, scpi_bool_t mandatory) { scpi_bool_t result; scpi_parameter_t param; if (!value || !len) { SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); return FALSE; } result = SCPI_Parameter(context, ¶m, mandatory); if (result) { if (param.type == SCPI_TOKEN_ARBITRARY_BLOCK_PROGRAM_DATA) { *value = param.ptr; *len = param.len; } else { SCPI_ErrorPush(context, SCPI_ERROR_DATA_TYPE_ERROR); result = FALSE; } } return result; }
/** * Read signed/unsigned 64 bit integer parameter * @param context * @param value * @param mandatory * @param sign * @return */ static scpi_bool_t ParamSignUInt64(scpi_t * context, uint64_t * value, scpi_bool_t mandatory, scpi_bool_t sign) { scpi_bool_t result; scpi_parameter_t param; if (!value) { SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); return FALSE; } result = SCPI_Parameter(context, ¶m, mandatory); if (result) { if (SCPI_ParamIsNumber(¶m, FALSE)) { result = ParamSignToUInt64(context, ¶m, value, sign); } else if (SCPI_ParamIsNumber(¶m, TRUE)) { SCPI_ErrorPush(context, SCPI_ERROR_SUFFIX_NOT_ALLOWED); result = FALSE; } else { SCPI_ErrorPush(context, SCPI_ERROR_DATA_TYPE_ERROR); result = FALSE; } } return result; }
/** * Read floating point double (64 bit) parameter * @param context * @param value * @param mandatory * @return */ scpi_bool_t SCPI_ParamDouble(scpi_t * context, double * value, scpi_bool_t mandatory) { scpi_bool_t result; scpi_parameter_t param; if (!value) { SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); return FALSE; } result = SCPI_Parameter(context, ¶m, mandatory); if (result) { if (SCPI_ParamIsNumber(¶m, FALSE)) { SCPI_ParamToDouble(context, ¶m, value); } else if (SCPI_ParamIsNumber(¶m, TRUE)) { SCPI_ErrorPush(context, SCPI_ERROR_SUFFIX_NOT_ALLOWED); result = FALSE; } else { SCPI_ErrorPush(context, SCPI_ERROR_DATA_TYPE_ERROR); result = FALSE; } } return result; }
/** * @brief * parses lists * channel numbers > 0. * no checks yet. * valid: (@1), (@3!1:1!3), ... * (@1!1:3!2) would be 1!1, 1!2, 2!1, 2!2, 3!1, 3!2. * (@3!1:1!3) would be 3!1, 3!2, 3!3, 2!1, 2!2, 2!3, ... 1!3. * * @param channel_list channel list, compare to SCPI99 Vol 1 Ch. 8.3.2 */ static scpi_result_t TEST_Chanlst(scpi_t *context) { scpi_parameter_t channel_list_param; #define MAXROW 2 /* maximum number of rows */ #define MAXCOL 6 /* maximum number of columns */ #define MAXDIM 2 /* maximum number of dimensions */ scpi_channel_value_t array[MAXROW * MAXCOL]; /* array which holds values in order (2D) */ size_t chanlst_idx; /* index for channel list */ size_t arr_idx = 0; /* index for array */ size_t n, m = 1; /* counters for row (n) and columns (m) */ /* get channel list */ if (SCPI_Parameter(context, &channel_list_param, TRUE)) { scpi_expr_result_t res; scpi_bool_t is_range; int32_t values_from[MAXDIM]; int32_t values_to[MAXDIM]; size_t dimensions; bool for_stop_row = FALSE; /* true if iteration for rows has to stop */ bool for_stop_col = FALSE; /* true if iteration for columns has to stop */ int32_t dir_row = 1; /* direction of counter for rows, +/-1 */ int32_t dir_col = 1; /* direction of counter for columns, +/-1 */ /* the next statement is valid usage and it gets only real number of dimensions for the first item (index 0) */ if (!SCPI_ExprChannelListEntry(context, &channel_list_param, 0, &is_range, NULL, NULL, 0, &dimensions)) { chanlst_idx = 0; /* call first index */ arr_idx = 0; /* set arr_idx to 0 */ do { /* if valid, iterate over channel_list_param index while res == valid (do-while cause we have to do it once) */ res = SCPI_ExprChannelListEntry(context, &channel_list_param, chanlst_idx, &is_range, values_from, values_to, 4, &dimensions); if (is_range == FALSE) { /* still can have multiple dimensions */ if (dimensions == 1) { /* here we have our values * row == values_from[0] * col == 0 (fixed number) * call a function or something */ array[arr_idx].row = values_from[0]; array[arr_idx].col = 0; } else if (dimensions == 2) { /* here we have our values * row == values_fom[0] * col == values_from[1] * call a function or something */ array[arr_idx].row = values_from[0]; array[arr_idx].col = values_from[1]; } else { return SCPI_RES_ERR; } arr_idx++; /* inkrement array where we want to save our values to, not neccessary otherwise */ if (arr_idx >= MAXROW * MAXCOL) { return SCPI_RES_ERR; } } else if (is_range == TRUE) { if (values_from[0] > values_to[0]) { dir_row = -1; /* we have to decrement from values_from */ } else { /* if (values_from[0] < values_to[0]) */ dir_row = +1; /* default, we increment from values_from */ } /* iterating over rows, do it once -> set for_stop_row = false * needed if there is channel list index isn't at end yet */ for_stop_row = FALSE; for (n = values_from[0]; for_stop_row == FALSE; n += dir_row) { /* usual case for ranges, 2 dimensions */ if (dimensions == 2) { if (values_from[1] > values_to[1]) { dir_col = -1; } else if (values_from[1] < values_to[1]) { dir_col = +1; } /* iterating over columns, do it at least once -> set for_stop_col = false * needed if there is channel list index isn't at end yet */ for_stop_col = FALSE; for (m = values_from[1]; for_stop_col == FALSE; m += dir_col) { /* here we have our values * row == n * col == m * call a function or something */ array[arr_idx].row = n; array[arr_idx].col = m; arr_idx++; if (arr_idx >= MAXROW * MAXCOL) { return SCPI_RES_ERR; } if (m == (size_t)values_to[1]) { /* endpoint reached, stop column for-loop */ for_stop_col = TRUE; } } /* special case for range, example: (@2!1) */ } else if (dimensions == 1) { /* here we have values * row == n * col == 0 (fixed number) * call function or sth. */ array[arr_idx].row = n; array[arr_idx].col = 0; arr_idx++; if (arr_idx >= MAXROW * MAXCOL) { return SCPI_RES_ERR; } } if (n == (size_t)values_to[0]) { /* endpoint reached, stop row for-loop */ for_stop_row = TRUE; } } } else { return SCPI_RES_ERR; } /* increase index */ chanlst_idx++; } while (SCPI_EXPR_OK == SCPI_ExprChannelListEntry(context, &channel_list_param, chanlst_idx, &is_range, values_from, values_to, 4, &dimensions)); /* while checks, whether incremented index is valid */ } /* do something at the end if needed */ /* array[arr_idx].row = 0; */ /* array[arr_idx].col = 0; */ } { size_t i; fprintf(stderr, "TEST_Chanlst: "); for (i = 0; i< arr_idx; i++) { fprintf(stderr, "%d!%d, ", array[i].row, array[i].col); } fprintf(stderr, "\r\n"); } return SCPI_RES_OK; }
/** * Parse parameter as number, number with unit or special value (min, max, default, ...) * @param context * @param value return value * @param mandatory if the parameter is mandatory * @return */ scpi_bool_t SCPI_ParamNumber(scpi_t * context, const scpi_choice_def_t * special, scpi_number_t * value, scpi_bool_t mandatory) { scpi_token_t token; lex_state_t state; scpi_parameter_t param; scpi_bool_t result; int32_t tag; if (!value) { SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); return FALSE; } result = SCPI_Parameter(context, ¶m, mandatory); if (!result) { return result; } state.buffer = param.ptr; state.pos = state.buffer; state.len = param.len; switch(param.type) { case SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA: case SCPI_TOKEN_HEXNUM: case SCPI_TOKEN_OCTNUM: case SCPI_TOKEN_BINNUM: case SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA_WITH_SUFFIX: case SCPI_TOKEN_PROGRAM_MNEMONIC: value->unit = SCPI_UNIT_NONE; value->special = FALSE; result = TRUE; break; } switch(param.type) { case SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA: case SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA_WITH_SUFFIX: case SCPI_TOKEN_PROGRAM_MNEMONIC: value->base = 10; break; case SCPI_TOKEN_BINNUM: value->base = 2; break; case SCPI_TOKEN_HEXNUM: value->base = 16; break; case SCPI_TOKEN_OCTNUM: value->base = 8; break; } switch(param.type) { case SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA: SCPI_ParamToDouble(context, ¶m, &(value->value)); break; case SCPI_TOKEN_HEXNUM: SCPI_ParamToDouble(context, ¶m, &(value->value)); break; case SCPI_TOKEN_OCTNUM: SCPI_ParamToDouble(context, ¶m, &(value->value)); break; case SCPI_TOKEN_BINNUM: SCPI_ParamToDouble(context, ¶m, &(value->value)); break; case SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA_WITH_SUFFIX: scpiLex_DecimalNumericProgramData(&state, &token); scpiLex_WhiteSpace(&state, &token); scpiLex_SuffixProgramData(&state, &token); SCPI_ParamToDouble(context, ¶m, &(value->value)); result = transformNumber(context, token.ptr, token.len, value); break; case SCPI_TOKEN_PROGRAM_MNEMONIC: scpiLex_WhiteSpace(&state, &token); scpiLex_CharacterProgramData(&state, &token); /* convert string to special number type */ SCPI_ParamToChoice(context, &token, special, &tag); value->special = TRUE; value->tag = tag; break; default: result = FALSE; } return result; }
/** * @brief * parses lists * channel numbers > 0. * no checks yet. * valid: (@1), (@3!1:1!3), ... * (@1!1:3!2) would be 1!1, 1!2, 2!1, 2!2, 3!1, 3!2. * (@3!1:1!3) would be 3!1, 3!2, 3!3, 2!1, 2!2, 2!3, ... 1!3. * * @param channel_list channel list, compare to SCPI99 Vol 1 Ch. 8.3.2 */ static scpi_result_t TEST_Chanlst(scpi_t *context) { scpi_parameter_t channel_list_param; #define maxrow 2 //maximum number of rows #define maxcol 6 //maximum number of columns #define maxdim 2 //maximum number of dimensions scpi_channel_value_t array[maxrow * maxcol]; //array which holds values in order (2D) size_t chanlst_idx; //index for channel list size_t arr_idx = 0; //index for array size_t n, m = 1; //counters for row (n) and columns (m) // get channel list if (SCPI_Parameter(context, &channel_list_param, TRUE)) { scpi_expr_result_t res; scpi_bool_t is_range; INT32 values_from[maxdim]; INT32 values_to[maxdim]; size_t dimensions; boolean for_stop_row = FALSE; //TRUE if iteration for rows has to stop boolean for_stop_col = FALSE; //TRUE if iteration for columns has to stop INT32 dir_row = 1; //direction of counter for rows, +/-1 INT32 dir_col = 1; //direction of counter for columns, +/-1 // the next statement is valid usage and it gets only real number of dimensions for the first item (index 0) if (!SCPI_ExprChannelListEntry(context, &channel_list_param, 0, &is_range, NULL, NULL, 0, &dimensions)) { chanlst_idx = 0; //call first index arr_idx = 0; //set arr_idx to 0 do { //if valid, iterate over channel_list_param index while res == valid (do-while cause we have to do it once) res = SCPI_ExprChannelListEntry(context, &channel_list_param, chanlst_idx, &is_range, values_from, values_to, 4, &dimensions); if (is_range == FALSE) { //still can have multiple dimensions if (dimensions == 1) { //here we have our values //row == values_from[0] //col == 0 (fixed number) //call a function or something array[arr_idx].row = values_from[0]; array[arr_idx].col = 0; } else if (dimensions == 2) { //here we have our values //row == values_fom[0] //col == values_from[1] //call a function or something array[arr_idx].row = values_from[0]; array[arr_idx].col = values_from[1]; } else { return SCPI_RES_ERR; break; } arr_idx++; //inkrement array where we want to save our values to, not neccessary otherwise } else if (is_range == TRUE) { if (values_from[0] > values_to[0]) { dir_row = -1; //we have to decrement from values_from } else { //if (values_from[0] < values_to[0]) dir_row = +1; //default, we increment from values_from } //iterating over rows, do it once -> set for_stop_row = FALSE //needed if there is channel list index isn't at end yet for_stop_row = FALSE; for (n = values_from[0]; for_stop_row == FALSE; n += dir_row) { //usual case for ranges, 2 dimensions if (dimensions == 2) { if (values_from[1] > values_to[1]) { dir_col = -1; } else if (values_from[1] < values_to[1]) { dir_col = +1; } //iterating over columns, do it at least once -> set for_stop_col = FALSE //needed if there is channel list index isn't at end yet for_stop_col = FALSE; for (m = values_from[1]; for_stop_col == FALSE; m += dir_col) { //here we have our values //row == n //col == m //call a function or something array[arr_idx].row = n; array[arr_idx].col = m; arr_idx++; if (m == (size_t)values_to[1]) { //endpoint reached, stop column for-loop for_stop_col = TRUE; } } //special case for range, example: (@2!1) } else if (dimensions == 1) { //here we have values //row == n //col == 0 (fixed number) //call function or sth. array[arr_idx].row = n; array[arr_idx].col = 0; arr_idx++; } if (n == (size_t)values_to[0]) { //endpoint reached, stop row for-loop for_stop_row = TRUE; } } } else { return SCPI_RES_ERR; break; } //increase index chanlst_idx++; } while (SCPI_EXPR_OK == SCPI_ExprChannelListEntry(context, &channel_list_param, chanlst_idx, &is_range, values_from, values_to, 4, &dimensions)); //while checks, whether incremented index is valid } //do something at the end if needed array[arr_idx].row = 0; array[arr_idx].col = 0; } { size_t i; fprintf(stderr, "TEST_Chanlst: "); for (i = 0; i< arr_idx; i++) { fprintf(stderr, "%d!%d, ", array[i].row, array[i].col); } fprintf(stderr, "\r\n"); } return SCPI_RES_OK; }