From b4e38d7ea765422bf301980634b7b948fe989ae1 Mon Sep 17 00:00:00 2001 From: Jan Breuer <jan.breuer@jaybee.cz> Date: 周三, 19 6月 2013 23:10:02 +0800 Subject: [PATCH] Convert parameter handling to new lexer --- libscpi/inc/scpi/units.h | 4 libscpi/src/minimal.c | 11 libscpi/src/parser.c | 297 +++++++++++------------------ examples/common/scpi-def.c | 24 +- libscpi/inc/scpi/error.h | 5 libscpi/inc/scpi/types.h | 32 ++ libscpi/src/ieee488.c | 18 libscpi/src/units.c | 133 ++++++------- libscpi/test/test_scpi_utils.c | 30 +- libscpi/src/debug.c | 6 libscpi/src/utils.h | 4 libscpi/inc/scpi/parser.h | 18 + libscpi/src/utils.c | 7 13 files changed, 269 insertions(+), 320 deletions(-) diff --git a/examples/common/scpi-def.c b/examples/common/scpi-def.c index 485cd85..d35ddf7 100644 --- a/examples/common/scpi-def.c +++ b/examples/common/scpi-def.c @@ -41,26 +41,26 @@ #include "scpi-def.h" scpi_result_t DMM_MeasureVoltageDcQ(scpi_t * context) { - scpi_number_t param1, param2; + scpi_parameter_t param1, param2; char bf[15]; fprintf(stderr, "meas:volt:dc\r\n"); // debug command name // read first parameter if present - if (!SCPI_ParamNumber(context, ¶m1, false)) { - // do something, if parameter not present + if (SCPI_Parameter(context, ¶m1, false)) { + SCPI_ParamTranslateNumberVal(context, ¶m1); } // read second paraeter if present - if (!SCPI_ParamNumber(context, ¶m2, false)) { - // do something, if parameter not present + if (SCPI_Parameter(context, ¶m2, false)) { + SCPI_ParamTranslateNumberVal(context, ¶m2); } - SCPI_NumberToStr(context, ¶m1, bf, 15); + SCPI_NumberToStr(context, ¶m1.number, bf, 15); fprintf(stderr, "\tP1=%s\r\n", bf); - SCPI_NumberToStr(context, ¶m2, bf, 15); + SCPI_NumberToStr(context, ¶m2.number, bf, 15); fprintf(stderr, "\tP2=%s\r\n", bf); SCPI_ResultDouble(context, 0); @@ -70,21 +70,21 @@ scpi_result_t DMM_ConfigureVoltageDc(scpi_t * context) { - double param1, param2; + scpi_parameter_t param1, param2; fprintf(stderr, "conf:volt:dc\r\n"); // debug command name // read first parameter if present - if (!SCPI_ParamDouble(context, ¶m1, true)) { + if (!SCPI_Parameter(context, ¶m1, true)) { return SCPI_RES_ERR; } // read second paraeter if present - if (!SCPI_ParamDouble(context, ¶m2, false)) { + if (!SCPI_Parameter(context, ¶m2, false)) { // do something, if parameter not present } - fprintf(stderr, "\tP1=%lf\r\n", param1); - fprintf(stderr, "\tP2=%lf\r\n", param2); + fprintf(stderr, "\tP1=%lf\r\n", SCPI_ParamGetDoubleVal(context, ¶m1)); + fprintf(stderr, "\tP2=%lf\r\n", SCPI_ParamGetDoubleVal(context, ¶m2)); return SCPI_RES_OK; } diff --git a/libscpi/inc/scpi/error.h b/libscpi/inc/scpi/error.h index cb5b398..615e9da 100644 --- a/libscpi/inc/scpi/error.h +++ b/libscpi/inc/scpi/error.h @@ -57,7 +57,10 @@ #define SCPI_ERROR_MISSING_PARAMETER -109 #define SCPI_ERROR_INVALID_SUFFIX -131 #define SCPI_ERROR_SUFFIX_NOT_ALLOWED -138 - +#define SCPI_ERROR_UNKNOWN_PARAMETER -199 // TODO: fix name and value +#define SCPI_ERROR_INVALID_PARAMETER -198 // TODO: fix name and value + + #define SCPI_ERROR_EXECUTION_ERROR -200 #ifdef __cplusplus diff --git a/libscpi/inc/scpi/parser.h b/libscpi/inc/scpi/parser.h index 172b0d4..6a9ebda 100644 --- a/libscpi/inc/scpi/parser.h +++ b/libscpi/inc/scpi/parser.h @@ -50,21 +50,27 @@ int SCPI_Parse(scpi_t * context, const char * data, int len); - size_t SCPI_ResultString(scpi_t * context, const char * data); + size_t SCPI_ResultCharacters(scpi_t * context, const char * data, size_t len); size_t SCPI_ResultInt(scpi_t * context, int32_t val); + size_t SCPI_ResultIntBase(scpi_t * context, int32_t val, int8_t base); size_t SCPI_ResultDouble(scpi_t * context, double val); size_t SCPI_ResultText(scpi_t * context, const char * data); + size_t SCPI_ResultArbitraryBlock(scpi_t * context, const char * data, size_t len); - bool_t SCPI_ParamInt(scpi_t * context, int32_t * value, bool_t mandatory); - bool_t SCPI_ParamDouble(scpi_t * context, double * value, bool_t mandatory); - bool_t SCPI_ParamString(scpi_t * context, const char ** value, size_t * len, bool_t mandatory); - bool_t SCPI_ParamText(scpi_t * context, const char ** value, size_t * len, bool_t mandatory); + int32_t SCPI_ParamGetIntVal(scpi_t * context, scpi_parameter_t * parameter); + double SCPI_ParamGetDoubleVal(scpi_t * context, scpi_parameter_t * parameter); + void SCPI_ParamGetTextVal(scpi_t * context, scpi_parameter_t * parameter, const char ** data, int32_t * len); +#define SCPI_ParamGetCharactersVal SCPI_ParamGetTextVal +#define SCPI_ParamGetArbitraryBlockVal SCPI_ParamGetTextVal + + bool_t SCPI_Parameter(scpi_t * context, scpi_parameter_t * parameter, bool_t mandatory); + int SCPI_ParseProgramData(lex_state_t * state, token_t * token); int SCPI_ParseAllProgramData(lex_state_t * state, token_t * token, int * numberOfParameters); int SCPI_DetectProgramMessageUnit(scpi_parser_state_t * state, const char * buffer, int len); - + #ifdef __cplusplus } #endif diff --git a/libscpi/inc/scpi/types.h b/libscpi/inc/scpi/types.h index 7dcca59..5369cdc 100644 --- a/libscpi/inc/scpi/types.h +++ b/libscpi/inc/scpi/types.h @@ -101,13 +101,7 @@ typedef struct _scpi_command_t scpi_command_t; - struct _scpi_param_list_t { - const scpi_command_t * cmd; - const char * parameters; - size_t length; - }; #define SCPI_CMD_LIST_END {NULL, NULL, } - typedef struct _scpi_param_list_t scpi_param_list_t; /* scpi interface */ typedef struct _scpi_t scpi_t; @@ -227,13 +221,33 @@ #define SCPI_SPECIAL_NUMBERS_LIST_END {NULL, SCPI_NUM_NUMBER} typedef struct _scpi_special_number_def_t scpi_special_number_def_t; - struct _scpi_number_t { + struct _scpi_param_list_t { + const scpi_command_t * cmd; + lex_state_t lex_state; + }; + typedef struct _scpi_param_list_t scpi_param_list_t; + + struct _scpi_number_parameter_t { double value; scpi_unit_t unit; + int8_t base; scpi_special_number_t type; }; - typedef struct _scpi_number_t scpi_number_t; + typedef struct _scpi_number_parameter_t scpi_number_parameter_t; + struct _scpi_data_parameter_t { + const char * ptr; + int32_t len; + }; + typedef struct _scpi_data_parameter_t scpi_data_parameter_t; + + struct _scpi_parameter_t { + token_type_t type; + scpi_data_parameter_t data; + scpi_number_parameter_t number; + }; + typedef struct _scpi_parameter_t scpi_parameter_t; + struct _scpi_command_t { const char * pattern; scpi_command_callback_t callback; @@ -251,7 +265,7 @@ struct _scpi_t { const scpi_command_t * cmdlist; scpi_buffer_t buffer; - scpi_param_list_t paramlist; + scpi_param_list_t param_list; scpi_interface_t * interface; int_fast16_t output_count; int_fast16_t input_count; diff --git a/libscpi/inc/scpi/units.h b/libscpi/inc/scpi/units.h index 8a06301..fb93cbd 100644 --- a/libscpi/inc/scpi/units.h +++ b/libscpi/inc/scpi/units.h @@ -46,8 +46,8 @@ extern const scpi_unit_def_t scpi_units_def[]; extern const scpi_special_number_def_t scpi_special_numbers_def[]; - bool_t SCPI_ParamNumber(scpi_t * context, scpi_number_t * value, bool_t mandatory); - size_t SCPI_NumberToStr(scpi_t * context, scpi_number_t * value, char * str, size_t len); + bool_t SCPI_ParamTranslateNumberVal(scpi_t * context, scpi_parameter_t * parameter); + size_t SCPI_NumberToStr(scpi_t * context, scpi_number_parameter_t * value, char * str, size_t len); #ifdef __cplusplus } diff --git a/libscpi/src/debug.c b/libscpi/src/debug.c index a0b5f57..0b85247 100644 --- a/libscpi/src/debug.c +++ b/libscpi/src/debug.c @@ -44,10 +44,10 @@ */ bool_t SCPI_DebugCommand(scpi_t * context) { size_t res; - printf("**DEBUG: %s (\"", context->paramlist.cmd->pattern); - res = fwrite(context->paramlist.parameters, 1, context->paramlist.length, stdout); + printf("**DEBUG: %s (\"", context->param_list.cmd->pattern); + res = fwrite(context->param_list.lex_state.buffer, 1, context->param_list.lex_state.len, stdout); (void)res; - printf("\" - %lu\r\n", (unsigned long)context->paramlist.length); + printf("\" - %lu\r\n", (unsigned long)context->param_list.lex_state.len); return TRUE; } diff --git a/libscpi/src/ieee488.c b/libscpi/src/ieee488.c index 2dc0662..5fd7fe9 100644 --- a/libscpi/src/ieee488.c +++ b/libscpi/src/ieee488.c @@ -210,9 +210,9 @@ * @return */ scpi_result_t SCPI_CoreEse(scpi_t * context) { - int32_t new_ESE; - if (SCPI_ParamInt(context, &new_ESE, TRUE)) { - SCPI_RegSet(context, SCPI_REG_ESE, new_ESE); + scpi_parameter_t parameter; + if (SCPI_Parameter(context, ¶meter, TRUE)) { + SCPI_RegSet(context, SCPI_REG_ESE, SCPI_ParamGetIntVal(context, ¶meter)); } return SCPI_RES_OK; } @@ -244,9 +244,9 @@ * @return */ scpi_result_t SCPI_CoreIdnQ(scpi_t * context) { - SCPI_ResultString(context, SCPI_MANUFACTURE); - SCPI_ResultString(context, SCPI_DEV_NAME); - SCPI_ResultString(context, SCPI_DEV_VERSION); + SCPI_ResultText(context, SCPI_MANUFACTURE); + SCPI_ResultText(context, SCPI_DEV_NAME); + SCPI_ResultText(context, SCPI_DEV_VERSION); return SCPI_RES_OK; } @@ -289,9 +289,9 @@ * @return */ scpi_result_t SCPI_CoreSre(scpi_t * context) { - int32_t new_SRE; - if (SCPI_ParamInt(context, &new_SRE, TRUE)) { - SCPI_RegSet(context, SCPI_REG_SRE, new_SRE); + scpi_parameter_t parameter; + if (SCPI_Parameter(context, ¶meter, TRUE)) { + SCPI_RegSet(context, SCPI_REG_SRE, SCPI_ParamGetIntVal(context, ¶meter)); } return SCPI_RES_OK; } diff --git a/libscpi/src/minimal.c b/libscpi/src/minimal.c index ec4680d..eab2624 100644 --- a/libscpi/src/minimal.c +++ b/libscpi/src/minimal.c @@ -57,7 +57,7 @@ * @return */ scpi_result_t SCPI_StubQ(scpi_t * context) { - SCPI_ResultString(context, ""); + SCPI_ResultInt(context, 0); return SCPI_RES_OK; } @@ -67,7 +67,7 @@ * @return */ scpi_result_t SCPI_SystemVersionQ(scpi_t * context) { - SCPI_ResultString(context, SCPI_DEV_VERSION); + SCPI_ResultText(context, SCPI_DEV_VERSION); return SCPI_RES_OK; } @@ -129,10 +129,11 @@ * @return */ scpi_result_t SCPI_StatusQuestionableEnable(scpi_t * context) { - int32_t new_QUESE; - if (SCPI_ParamInt(context, &new_QUESE, TRUE)) { - SCPI_RegSet(context, SCPI_REG_QUESE, new_QUESE); + scpi_parameter_t parameter; + if (SCPI_Parameter(context, ¶meter, TRUE)) { + SCPI_RegSet(context, SCPI_REG_QUESE, SCPI_ParamGetIntVal(context, ¶meter)); } + return SCPI_RES_OK; } diff --git a/libscpi/src/parser.c b/libscpi/src/parser.c index aa3806a..99de301 100644 --- a/libscpi/src/parser.c +++ b/libscpi/src/parser.c @@ -43,28 +43,6 @@ #include "utils.h" #include "scpi/error.h" -static void paramSkipBytes(scpi_t * context, size_t num); -static void paramSkipWhitespace(scpi_t * context); -static bool_t paramNext(scpi_t * context, bool_t mandatory); - -/* -int _strnicmp(const char* s1, const char* s2, int len) { - int result = 0; - int i; - - for (i = 0; i < len && s1[i] && s2[i]; i++) { - char c1 = tolower(s1[i]); - char c2 = tolower(s2[i]); - if (c1 != c2) { - result = (int) c1 - (int) c2; - break; - } - } - - return result; -} - */ - /** * Write data to SCPI output * @param context @@ -123,7 +101,8 @@ * @param context */ static void processCommand(scpi_t * context) { - const scpi_command_t * cmd = context->paramlist.cmd; + const scpi_command_t * cmd = context->param_list.cmd; + lex_state_t * state = &context->param_list.lex_state; context->cmd_error = FALSE; context->output_count = 0; @@ -140,11 +119,8 @@ /* conditionaly write new line */ writeNewLine(context); - /* skip all whitespaces */ - paramSkipWhitespace(context); - /* set error if command callback did not read all parameters */ - if (context->paramlist.length != 0 && !context->cmd_error) { + if (state->pos < (state->buffer + state->len) && !context->cmd_error) { SCPI_ErrorPush(context, SCPI_ERROR_PARAMETER_NOT_ALLOWED); } } @@ -161,7 +137,7 @@ for (i = 0; context->cmdlist[i].pattern != NULL; i++) { cmd = &context->cmdlist[i]; if (matchCommand(cmd->pattern, header, len)) { - context->paramlist.cmd = cmd; + context->param_list.cmd = cmd; return TRUE; } } @@ -194,8 +170,9 @@ if (state->programHeader.len > 0) { if (findCommandHeader(context, state->programHeader.ptr, state->programHeader.len)) { - context->paramlist.parameters = state->programData.ptr; - context->paramlist.length = state->programData.len; + context->param_list.lex_state.buffer = state->programData.ptr; + context->param_list.lex_state.pos = context->param_list.lex_state.buffer; + context->param_list.lex_state.len = state->programData.len; processCommand(context); @@ -285,8 +262,7 @@ * @param data * @return */ -size_t SCPI_ResultString(scpi_t * context, const char * data) { - size_t len = strlen(data); +size_t SCPI_ResultCharacters(scpi_t * context, const char * data, size_t len) { size_t result = 0; result += writeDelimiter(context); result += writeData(context, data, len); @@ -301,10 +277,31 @@ * @return */ size_t SCPI_ResultInt(scpi_t * context, int32_t val) { - char buffer[12]; + return SCPI_ResultIntBase(context, val, 10); +} + +static const char * getBasePrefix(int8_t base) { + switch (base) { + case 2: return "#B"; + case 8: return "#Q"; + case 16: return "#H"; + default: return NULL; + } +} + +size_t SCPI_ResultIntBase(scpi_t * context, int32_t val, int8_t base) { + char buffer[33]; + const char * basePrefix; size_t result = 0; - size_t len = longToStr(val, buffer, sizeof (buffer)); + size_t len; + + len = longToStr(val, buffer, sizeof (buffer), base); + basePrefix = getBasePrefix(base); + result += writeDelimiter(context); + if (basePrefix != NULL) { + result += writeData(context, basePrefix, 2); + } result += writeData(context, buffer, len); context->output_count++; return result; @@ -345,174 +342,110 @@ /* parsing parameters */ -/** - * Skip num bytes from the begginig of parameters - * @param context - * @param num - */ -void paramSkipBytes(scpi_t * context, size_t num) { - if (context->paramlist.length < num) { - num = context->paramlist.length; - } - context->paramlist.parameters += num; - context->paramlist.length -= num; -} +bool_t SCPI_Parameter(scpi_t * context, scpi_parameter_t * parameter, bool_t mandatory) { + token_t token; + lex_state_t * state; + int32_t value; -/** - * Skip white spaces from the beggining of parameters - * @param context - */ -void paramSkipWhitespace(scpi_t * context) { - size_t ws = skipWhitespace(context->paramlist.parameters, context->paramlist.length); - paramSkipBytes(context, ws); -} + parameter->data.ptr = NULL; + parameter->data.len = 0; + parameter->number.value = 0; + parameter->number.base = 10; + parameter->number.unit = SCPI_UNIT_NONE; + parameter->number.type = SCPI_NUM_NUMBER; + parameter->type = TokUnknown; -/** - * Find next parameter - * @param context - * @param mandatory - * @return - */ -bool_t paramNext(scpi_t * context, bool_t mandatory) { - paramSkipWhitespace(context); - if (context->paramlist.length == 0) { + state = &context->param_list.lex_state; + + if (state->pos >= (state->buffer + state->len)) { if (mandatory) { SCPI_ErrorPush(context, SCPI_ERROR_MISSING_PARAMETER); + } else { + parameter->number.type = SCPI_NUM_DEF; + parameter->type = TokProgramMnemonic; // TODO: select something different } return FALSE; } if (context->input_count != 0) { - if (context->paramlist.parameters[0] == ',') { - paramSkipBytes(context, 1); - paramSkipWhitespace(context); - } else { + SCPI_LexComma(state, &token); + if (token.type != TokComma) { SCPI_ErrorPush(context, SCPI_ERROR_INVALID_SEPARATOR); return FALSE; } } + context->input_count++; - return TRUE; + + SCPI_ParseProgramData(&context->param_list.lex_state, &token); + + parameter->type = token.type; + parameter->data.ptr = token.ptr; + parameter->data.len = token.len; + + switch (token.type) { + case TokHexnum: + parameter->number.base = 16; + strToLong(token.ptr, &value, 16); + parameter->number.value = value; + return TRUE; + case TokOctnum: + parameter->number.base = 8; + strToLong(token.ptr, &value, 8); + parameter->number.value = value; + return TRUE; + case TokBinnum: + parameter->number.base = 2; + strToLong(token.ptr, &value, 2); + parameter->number.value = value; + return TRUE; + case TokProgramMnemonic: + return TRUE; + case TokDecimalNumericProgramData: + strToDouble(token.ptr, ¶meter->number.value); + return TRUE; + case TokDecimalNumericProgramDataWithSuffix: + strToDouble(token.ptr, ¶meter->number.value); + return TRUE; + case TokArbitraryBlockProgramData: + return TRUE; + case TokSingleQuoteProgramData: + // TODO: replace double "single qoute" + return TRUE; + case TokDoubleQuoteProgramData: + // TODO: replace double "double qoute" + return TRUE; + case TokProgramExpression: + return TRUE; + default: + parameter->type = TokUnknown; + parameter->data.ptr = NULL; + parameter->data.len = 0; + SCPI_ErrorPush(context, SCPI_ERROR_UNKNOWN_PARAMETER); + return FALSE; + } } -/** - * Parse integer parameter - * @param context - * @param value - * @param mandatory - * @return - */ -bool_t SCPI_ParamInt(scpi_t * context, int32_t * value, bool_t mandatory) { - const char * param; - size_t param_len; - size_t num_len; - - if (!value) { - return FALSE; +int32_t SCPI_ParamGetIntVal(scpi_t * context, scpi_parameter_t * parameter) { + switch (parameter->type) { + case TokHexnum: + case TokOctnum: + case TokBinnum: + case TokDecimalNumericProgramData: + case TokDecimalNumericProgramDataWithSuffix: + return parameter->number.value; + default: + SCPI_ErrorPush(context, SCPI_ERROR_INVALID_PARAMETER); + return 0; } - - if (!SCPI_ParamString(context, ¶m, ¶m_len, mandatory)) { - return FALSE; - } - - num_len = strToLong(param, value); - - if (num_len != param_len) { - SCPI_ErrorPush(context, SCPI_ERROR_SUFFIX_NOT_ALLOWED); - return FALSE; - } - - return TRUE; } -/** - * Parse double parameter - * @param context - * @param value - * @param mandatory - * @return - */ -bool_t SCPI_ParamDouble(scpi_t * context, double * value, bool_t mandatory) { - const char * param; - size_t param_len; - size_t num_len; - - if (!value) { - return FALSE; - } - - if (!SCPI_ParamString(context, ¶m, ¶m_len, mandatory)) { - return FALSE; - } - - num_len = strToDouble(param, value); - - if (num_len != param_len) { - SCPI_ErrorPush(context, SCPI_ERROR_SUFFIX_NOT_ALLOWED); - return FALSE; - } - - return TRUE; +double SCPI_ParamGetDoubleVal(scpi_t * context, scpi_parameter_t * parameter) { + return parameter->number.value; } -/** - * Parse string parameter - * @param context - * @param value - * @param len - * @param mandatory - * @return - */ -bool_t SCPI_ParamString(scpi_t * context, const char ** value, size_t * len, bool_t mandatory) { - size_t length; - - if (!value || !len) { - return FALSE; - } - - if (!paramNext(context, mandatory)) { - return FALSE; - } - - if (locateStr(context->paramlist.parameters, context->paramlist.length, value, &length)) { - paramSkipBytes(context, length); - paramSkipWhitespace(context); - if (len) { - *len = length; - } - return TRUE; - } - - return FALSE; -} - -/** - * Parse text parameter (can be inside "") - * @param context - * @param value - * @param len - * @param mandatory - * @return - */ -bool_t SCPI_ParamText(scpi_t * context, const char ** value, size_t * len, bool_t mandatory) { - size_t length; - - if (!value || !len) { - return FALSE; - } - - if (!paramNext(context, mandatory)) { - return FALSE; - } - - if (locateText(context->paramlist.parameters, context->paramlist.length, value, &length)) { - paramSkipBytes(context, length); - if (len) { - *len = length; - } - return TRUE; - } - - return FALSE; +void SCPI_ParamGetTextVal(scpi_t * context, scpi_parameter_t * parameter, const char ** data, int32_t * len) { + *data = parameter->data.ptr; + *len = parameter->data.len; } int SCPI_ParseProgramData(lex_state_t * state, token_t * token) { diff --git a/libscpi/src/units.c b/libscpi/src/units.c index 493c4ce..3583ef5 100644 --- a/libscpi/src/units.c +++ b/libscpi/src/units.c @@ -39,6 +39,7 @@ #include "scpi/units.h" #include "utils.h" #include "scpi/error.h" +#include "scpi/lexer.h" /* @@ -62,39 +63,39 @@ */ const scpi_unit_def_t scpi_units_def[] = { /* voltage */ - {/* name */ "UV", /* unit */ SCPI_UNIT_VOLT, /* mult */ 1e-6}, - {/* name */ "MV", /* unit */ SCPI_UNIT_VOLT, /* mult */ 1e-3}, - {/* name */ "V", /* unit */ SCPI_UNIT_VOLT, /* mult */ 1}, - {/* name */ "KV", /* unit */ SCPI_UNIT_VOLT, /* mult */ 1e3}, + {/* name */ "UV", /* unit */ SCPI_UNIT_VOLT, /* mult */ 1e-6}, + {/* name */ "MV", /* unit */ SCPI_UNIT_VOLT, /* mult */ 1e-3}, + {/* name */ "V", /* unit */ SCPI_UNIT_VOLT, /* mult */ 1}, + {/* name */ "KV", /* unit */ SCPI_UNIT_VOLT, /* mult */ 1e3}, /* current */ - {/* name */ "UA", /* unit */ SCPI_UNIT_AMPER, /* mult */ 1e-6}, - {/* name */ "MA", /* unit */ SCPI_UNIT_AMPER, /* mult */ 1e-3}, - {/* name */ "A", /* unit */ SCPI_UNIT_AMPER, /* mult */ 1}, - {/* name */ "KA", /* unit */ SCPI_UNIT_AMPER, /* mult */ 1e3}, + {/* name */ "UA", /* unit */ SCPI_UNIT_AMPER, /* mult */ 1e-6}, + {/* name */ "MA", /* unit */ SCPI_UNIT_AMPER, /* mult */ 1e-3}, + {/* name */ "A", /* unit */ SCPI_UNIT_AMPER, /* mult */ 1}, + {/* name */ "KA", /* unit */ SCPI_UNIT_AMPER, /* mult */ 1e3}, /* resistance */ - {/* name */ "OHM", /* unit */ SCPI_UNIT_OHM, /* mult */ 1}, - {/* name */ "KOHM", /* unit */ SCPI_UNIT_OHM, /* mult */ 1e3}, - {/* name */ "MOHM", /* unit */ SCPI_UNIT_OHM, /* mult */ 1e6}, + {/* name */ "OHM", /* unit */ SCPI_UNIT_OHM, /* mult */ 1}, + {/* name */ "KOHM", /* unit */ SCPI_UNIT_OHM, /* mult */ 1e3}, + {/* name */ "MOHM", /* unit */ SCPI_UNIT_OHM, /* mult */ 1e6}, /* frequency */ - {/* name */ "HZ", /* unit */ SCPI_UNIT_HERTZ, /* mult */ 1}, - {/* name */ "KHZ", /* unit */ SCPI_UNIT_HERTZ, /* mult */ 1e3}, - {/* name */ "MHZ", /* unit */ SCPI_UNIT_HERTZ, /* mult */ 1e6}, - {/* name */ "GHZ", /* unit */ SCPI_UNIT_HERTZ, /* mult */ 1e9}, + {/* name */ "HZ", /* unit */ SCPI_UNIT_HERTZ, /* mult */ 1}, + {/* name */ "KHZ", /* unit */ SCPI_UNIT_HERTZ, /* mult */ 1e3}, + {/* name */ "MHZ", /* unit */ SCPI_UNIT_HERTZ, /* mult */ 1e6}, + {/* name */ "GHZ", /* unit */ SCPI_UNIT_HERTZ, /* mult */ 1e9}, /* temperature */ - {/* name */ "CEL", /* unit */ SCPI_UNIT_CELSIUS, /* mult */ 1}, + {/* name */ "CEL", /* unit */ SCPI_UNIT_CELSIUS, /* mult */ 1}, /* time */ - {/* name */ "PS", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 1e-12}, - {/* name */ "NS", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 1e-9}, - {/* name */ "US", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 1e-6}, - {/* name */ "MS", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 1e-3}, - {/* name */ "S", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 1}, - {/* name */ "MIN", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 60}, - {/* name */ "HR", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 3600}, + {/* name */ "PS", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 1e-12}, + {/* name */ "NS", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 1e-9}, + {/* name */ "US", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 1e-6}, + {/* name */ "MS", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 1e-3}, + {/* name */ "S", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 1}, + {/* name */ "MIN", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 60}, + {/* name */ "HR", /* unit */ SCPI_UNIT_SECONDS, /* mult */ 3600}, SCPI_UNITS_LIST_END, }; @@ -103,14 +104,14 @@ * Special number values definition */ const scpi_special_number_def_t scpi_special_numbers_def[] = { - {/* name */ "MINimum", /* type */ SCPI_NUM_MIN}, - {/* name */ "MAXimum", /* type */ SCPI_NUM_MAX}, - {/* name */ "DEFault", /* type */ SCPI_NUM_DEF}, - {/* name */ "UP", /* type */ SCPI_NUM_UP}, - {/* name */ "DOWN", /* type */ SCPI_NUM_DOWN}, - {/* name */ "NAN", /* type */ SCPI_NUM_NAN}, - {/* name */ "INF", /* type */ SCPI_NUM_INF}, - {/* name */ "NINF", /* type */ SCPI_NUM_NINF}, + {/* name */ "MINimum", /* type */ SCPI_NUM_MIN}, + {/* name */ "MAXimum", /* type */ SCPI_NUM_MAX}, + {/* name */ "DEFault", /* type */ SCPI_NUM_DEF}, + {/* name */ "UP", /* type */ SCPI_NUM_UP}, + {/* name */ "DOWN", /* type */ SCPI_NUM_DOWN}, + {/* name */ "NAN", /* type */ SCPI_NUM_NAN}, + {/* name */ "INF", /* type */ SCPI_NUM_INF}, + {/* name */ "NINF", /* type */ SCPI_NUM_NINF}, SCPI_SPECIAL_NUMBERS_LIST_END, }; @@ -122,7 +123,7 @@ * @param value resultin value * @return TRUE if str matches one of specs patterns */ -static bool_t translateSpecialNumber(const scpi_special_number_def_t * specs, const char * str, size_t len, scpi_number_t * value) { +static bool_t translateSpecialNumber(const scpi_special_number_def_t * specs, const char * str, size_t len, scpi_number_parameter_t * value) { int i; value->value = 0.0; @@ -155,7 +156,7 @@ if (specs == NULL) { return NULL; } - + for (i = 0; specs[i].name != NULL; i++) { if (specs[i].type == type) { return specs[i].name; @@ -174,11 +175,11 @@ */ static const scpi_unit_def_t * translateUnit(const scpi_unit_def_t * units, const char * unit, size_t len) { int i; - + if (units == NULL) { return NULL; } - + for (i = 0; units[i].name != NULL; i++) { if (compareStr(unit, len, units[i].name, strlen(units[i].name))) { return &units[i]; @@ -196,11 +197,11 @@ */ static const char * translateUnitInverse(const scpi_unit_def_t * units, const scpi_unit_t unit) { int i; - + if (units == NULL) { return NULL; } - + for (i = 0; units[i].name != NULL; i++) { if ((units[i].unit == unit) && (units[i].mult == 1)) { return units[i].name; @@ -218,7 +219,7 @@ * @param value preparsed numeric value * @return TRUE if value parameter was converted to base units */ -static bool_t transformNumber(scpi_t * context, const char * unit, size_t len, scpi_number_t * value) { +static bool_t transformNumber(scpi_t * context, const char * unit, size_t len, scpi_number_parameter_t * value) { size_t s; const scpi_unit_def_t * unitDef; s = skipWhitespace(unit, len); @@ -248,43 +249,33 @@ * @param mandatory if the parameter is mandatory * @return */ -bool_t SCPI_ParamNumber(scpi_t * context, scpi_number_t * value, bool_t mandatory) { - bool_t result; - const char * param; - size_t len; - size_t numlen; +bool_t SCPI_ParamTranslateNumberVal(scpi_t * context, scpi_parameter_t * parameter) { + token_t token; + lex_state_t state; - /* read parameter and shift to the next one */ - result = SCPI_ParamString(context, ¶m, &len, mandatory); + state.buffer = parameter->data.ptr; + state.pos = state.buffer; + state.len = parameter->data.len; - /* value not initializes */ - if (!value) { - return FALSE; + if (parameter->type == TokDecimalNumericProgramDataWithSuffix) { + SCPI_LexDecimalNumericProgramData(&state, &token); + SCPI_LexWhiteSpace(&state, &token); + SCPI_LexSuffixProgramData(&state, &token); + + return transformNumber(context, token.ptr, token.len, ¶meter->number); + + } else if (parameter->type == TokProgramMnemonic) { + SCPI_LexWhiteSpace(&state, &token); + SCPI_LexCharacterProgramData(&state, &token); + + /* convert string to special number type */ + if (translateSpecialNumber(context->special_numbers, token.ptr, token.len, ¶meter->number)) { + /* found special type */ + return TRUE; + } } - value->type = SCPI_NUM_DEF; - - /* if parameter was not found, return TRUE or FALSE according - * to fact that parameter was mandatory or not */ - if (!result) { - return mandatory ? FALSE : TRUE; - } - - /* convert string to special number type */ - if (translateSpecialNumber(context->special_numbers, param, len, value)) { - /* found special type */ - return TRUE; - } - - /* convert text from double - no special type */ - numlen = strToDouble(param, &value->value); - - /* transform units of value */ - if (numlen <= len) { - return transformNumber(context, param + numlen, len - numlen, value); - } return FALSE; - } /** @@ -295,7 +286,7 @@ * @param len max length of string * @return number of chars written to string */ -size_t SCPI_NumberToStr(scpi_t * context, scpi_number_t * value, char * str, size_t len) { +size_t SCPI_NumberToStr(scpi_t * context, scpi_number_parameter_t * value, char * str, size_t len) { const char * type; const char * unit; size_t result; diff --git a/libscpi/src/utils.c b/libscpi/src/utils.c index 0562487..876ce01 100644 --- a/libscpi/src/utils.c +++ b/libscpi/src/utils.c @@ -74,7 +74,8 @@ * @param len string buffer length * @return number of bytes written to str (without '\0') */ -size_t longToStr(int32_t val, char * str, size_t len) { +// TODO: add support for other bases +size_t longToStr(int32_t val, char * str, size_t len, int8_t base) { uint32_t x = 1000000000L; int_fast8_t digit; size_t pos = 0; @@ -120,9 +121,9 @@ * @param val 32bit integer result * @return number of bytes used in string */ -size_t strToLong(const char * str, int32_t * val) { +size_t strToLong(const char * str, int32_t * val, int8_t base) { char * endptr; - *val = strtol(str, &endptr, 0); + *val = strtol(str, &endptr, base); return endptr - str; } diff --git a/libscpi/src/utils.h b/libscpi/src/utils.h index 6d3528f..f7c5c5b 100644 --- a/libscpi/src/utils.h +++ b/libscpi/src/utils.h @@ -53,9 +53,9 @@ char * strnpbrk(const char *str, size_t size, const char *set) LOCAL; bool_t compareStr(const char * str1, size_t len1, const char * str2, size_t len2) LOCAL; - size_t longToStr(int32_t val, char * str, size_t len) LOCAL; + size_t longToStr(int32_t val, char * str, size_t len, int8_t base) LOCAL; size_t doubleToStr(double val, char * str, size_t len) LOCAL; - size_t strToLong(const char * str, int32_t * val) LOCAL; + size_t strToLong(const char * str, int32_t * val, int8_t base) LOCAL; size_t strToDouble(const char * str, double * val) LOCAL; bool_t locateText(const char * str1, size_t len1, const char ** str2, size_t * len2) LOCAL; bool_t locateStr(const char * str1, size_t len1, const char ** str2, size_t * len2) LOCAL; diff --git a/libscpi/test/test_scpi_utils.c b/libscpi/test/test_scpi_utils.c index 059cc97..b3ab4c0 100644 --- a/libscpi/test/test_scpi_utils.c +++ b/libscpi/test/test_scpi_utils.c @@ -38,7 +38,7 @@ char str[32]; size_t len; - len = longToStr(10, str, 32); + len = longToStr(10, str, 32, 10); CU_ASSERT(len == 2); CU_ASSERT(str[0] == '1'); CU_ASSERT(str[1] == '0'); @@ -71,25 +71,25 @@ size_t result; int32_t val; -#define TEST_STR_TO_LONG(s, r, v) \ +#define TEST_STR_TO_LONG(s, r, v, b) \ do { \ - result = strToLong(s, &val); \ + result = strToLong(s, &val, b); \ CU_ASSERT_EQUAL(val, v); \ CU_ASSERT_EQUAL(result, r); \ } while(0) \ - TEST_STR_TO_LONG("", 0, 0); - TEST_STR_TO_LONG("1", 1, 1); - TEST_STR_TO_LONG("10", 2, 10); - TEST_STR_TO_LONG("-50", 3, -50); - TEST_STR_TO_LONG("100MHz", 3, 100); - TEST_STR_TO_LONG("MHz", 0, 0); - TEST_STR_TO_LONG("1.4", 1, 1); - TEST_STR_TO_LONG(" 1", 2, 1); - TEST_STR_TO_LONG(" +100", 5, 100); // space and + - TEST_STR_TO_LONG("0xFF", 4, 255); // hexadecimal FF - TEST_STR_TO_LONG("077", 3, 63); // octal 77 - TEST_STR_TO_LONG("018", 2, 1); // octal 1, 8 is ignored + TEST_STR_TO_LONG("", 0, 0, 10); + TEST_STR_TO_LONG("1", 1, 1, 10); + TEST_STR_TO_LONG("10", 2, 10, 10); + TEST_STR_TO_LONG("-50", 3, -50, 10); + TEST_STR_TO_LONG("100MHz", 3, 100, 10); + TEST_STR_TO_LONG("MHz", 0, 0, 10); + TEST_STR_TO_LONG("1.4", 1, 1, 10); + TEST_STR_TO_LONG(" 1", 2, 1, 10); + TEST_STR_TO_LONG(" +100", 5, 100, 10); // space and + + TEST_STR_TO_LONG("FF", 2, 255, 16); // hexadecimal FF + TEST_STR_TO_LONG("77", 2, 63, 8); // octal 77 + TEST_STR_TO_LONG("18", 1, 1, 8); // octal 1, 8 is ignored } void test_strToDouble() { -- Gitblit v1.9.1