scpi_args_helper.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. #define SCPI_ARGS_HELPER_C
  2. #define SCPI_CORE_PRIVATE // access to 'scpi_core_private.h'
  3. #include "app/scpi/scpi_core.h"
  4. #include "app/scpi/scpi_core_private.h"
  5. #include "app/scpi/scpi_parser.h"
  6. #include "app/scpi/scpi_commands.h" // processCharacterArgument
  7. #include "app/scpi/scpi_numeric.h" // processNumericArgument
  8. #include "app/scpi/scpi_args_helper.h"
  9. #include "app/fseq/fseq.h" // tFSeqCtx_t
  10. #include "app/scpi/CommandParserStates/process_data.h" // sProcessProgramDataCommonContext_t
  11. #include "my_assert.h"
  12. // [1] IEEE 488.2 Standard, revision IEEE Std 488.2-1987 (1992)
  13. // "IEEE Standard Codes, Formats, Protocols, and Common Commands for Use With IEEE Std 488.1-1987, IEEE
  14. // @parseArguments_helper
  15. // Helper function. Used for convenient call of @parseArguments inside command handler module
  16. // Parameters:
  17. // @common_ctx - process program data state context, see @sProcessProgramDataCommonContext_t
  18. // @argTypes - array of argument types to set the parameters parsing methods (see @parseArguments, @eScpiArgType_t)
  19. // Other parameters: refer @parseArguments
  20. // Returns: refer @parseArguments
  21. eScpiParserStatus_t parseArguments_helper( void * common_ctx, const uint8_t * argTypes, size_t argN, size_t argOptionalN)
  22. {
  23. assert( argN <= SCPI_MAX_ARGS );
  24. sProcessProgramDataCommonContext_t * _common_ctx = common_ctx;
  25. sScpiParserContext_t * global_ctx = _common_ctx->global_ctx;
  26. // parse command parameters
  27. eScpiParserStatus_t status = parseArguments( &(global_ctx->sParser.xCtxObj), _common_ctx->argTokens, argTypes, _common_ctx->argEntityTypes, argN, argOptionalN, &_common_ctx->args );
  28. // Modify state status value
  29. // This status can be used inside Dispatch routine of command handler
  30. _common_ctx->argsParserStatus = status;
  31. // check the parser status result
  32. if( eScpiParserStatus_success != status )
  33. {
  34. // _common_ctx->args is index of parameter
  35. assert( _common_ctx->args < SCPI_MAX_ARGS );
  36. // assign whole arguments chain token
  37. global_ctx->sParser.xArgToken.shead = _common_ctx->argTokens[_common_ctx->args].shead;
  38. global_ctx->sParser.xArgToken.stail = _common_ctx->argTokens[_common_ctx->args].stail;
  39. }
  40. else
  41. {
  42. // _common_ctx->args is amount of parameters
  43. assert( _common_ctx->args <= SCPI_MAX_ARGS );
  44. // assign whole arguments chain token
  45. global_ctx->sParser.xArgToken.shead = _common_ctx->argTokens[0].shead;
  46. global_ctx->sParser.xArgToken.stail = _common_ctx->argTokens[_common_ctx->args - 1].stail;
  47. }
  48. // Reset indicator: end-of-command has been parsed
  49. _common_ctx->needParseEndOfCommand = false;
  50. return status;
  51. }
  52. // [1] IEEE 488.2 Standard, revision IEEE Std 488.2-1987 (1992)
  53. // "IEEE Standard Codes, Formats, Protocols, and Common Commands for Use With IEEE Std 488.1-1987, IEEE
  54. // @parseArrayArguments_helper
  55. // Helper function. Used for convenient call of @parseArguments inside command handler module
  56. // Parameters:
  57. // @common_ctx - process program data state context, see @sProcessProgramDataCommonContext_t
  58. // @argTypes - array of argument types to set the parameters parsing methods (see @parseArguments, @eScpiArgType_t)
  59. // Other parameters: refer @parseArguments
  60. // Returns: refer @parseArguments
  61. eScpiParserStatus_t parseArrayArguments_helper( void * common_ctx, const uint8_t * argTypes, size_t argN, size_t argOptionalN)
  62. {
  63. assert( argN <= SCPI_MAX_ARGS );
  64. sProcessProgramDataCommonContext_t * _common_ctx = common_ctx;
  65. sScpiParserContext_t * global_ctx = _common_ctx->global_ctx;
  66. size_t argNumber = sizeof(_common_ctx->argArray)/sizeof(_common_ctx->argArray[0]);
  67. // parse command parameters
  68. eScpiParserStatus_t status = parseArrayArguments( &(global_ctx->sParser.xCtxObj), _common_ctx->argArray, &argNumber, argTypes, _common_ctx->argEntityTypes, argN, argOptionalN, &_common_ctx->args );
  69. // Modify state status value
  70. // This status can be used inside Dispatch routine of command handler
  71. _common_ctx->argsParserStatus = status;
  72. // check the parser status result
  73. if( eScpiParserStatus_success != status )
  74. {
  75. // _common_ctx->args is index of parameter
  76. //assert( _common_ctx->args < SCPI_MAX_ARGS );
  77. // assign whole arguments chain token
  78. global_ctx->sParser.xArgToken.shead = _common_ctx->argTokens[_common_ctx->args].shead;
  79. global_ctx->sParser.xArgToken.stail = _common_ctx->argTokens[_common_ctx->args].stail;
  80. }
  81. else
  82. {
  83. // _common_ctx->args is amount of parameters
  84. //assert( _common_ctx->args <= SCPI_MAX_ARGS );
  85. // assign whole arguments chain token
  86. global_ctx->sParser.xArgToken.shead = _common_ctx->argTokens[0].shead;
  87. global_ctx->sParser.xArgToken.stail = _common_ctx->argTokens[_common_ctx->args - 1].stail;
  88. }
  89. // Reset indicator: end-of-command has been parsed
  90. _common_ctx->needParseEndOfCommand = false;
  91. return status;
  92. }
  93. // @processArgument_Character_helper
  94. // Helper function. Used for convenient call of the other helper functions.
  95. // Processes the CHARACTER argument. See @processCharacterArgument
  96. // Parameters:
  97. // @common_ctx - process program data state context, see @sProcessProgramDataCommonContext_t
  98. // @argTypes - array of argument types to set the parameters parsing methods (see @parseArguments, @eScpiArgType_t)
  99. // Other parameters: refer @processCharacterArgument
  100. // Returns: SCPI_ARGUMENT_CHARACTER_INVALID_ID in error case, or argument option index in @allowedList
  101. int8_t processArgument_Character_helper( void * common_ctx, const uint8_t * argTypes, const xArgument_t * allowedList, uint8_t argId )
  102. {
  103. assert( common_ctx );
  104. assert( argTypes );
  105. if( NULL == common_ctx || NULL == argTypes )
  106. {
  107. return SCPI_ARGUMENT_CHARACTER_INVALID_ID;
  108. }
  109. assert( argTypes[ argId ] == eScpiArg_Character );
  110. // analyze argument type
  111. if( argTypes[ argId ] != eScpiArg_Character )
  112. {
  113. return SCPI_ARGUMENT_CHARACTER_INVALID_ID;
  114. }
  115. bool state = false;
  116. int8_t argument_idx = 0;
  117. sProcessProgramDataCommonContext_t * _common_ctx = common_ctx;
  118. sScpiParserContext_t * global_ctx = _common_ctx->global_ctx;
  119. state = processCharacterArgument( allowedList, &_common_ctx->argTokens[argId], &argument_idx );
  120. // assign current argument token (success or failed)
  121. global_ctx->sParser.xArgToken.shead = _common_ctx->argTokens[argId].shead;
  122. global_ctx->sParser.xArgToken.stail = _common_ctx->argTokens[argId].stail;
  123. if( ! state )
  124. {
  125. argument_idx = SCPI_ARGUMENT_CHARACTER_INVALID_ID;
  126. }
  127. return argument_idx;
  128. }
  129. // @processArgument_Numeric_helper
  130. // Helper function. Used for convenient call of the other helper functions.
  131. // Processes the NUMERIC argument. See @processNumericArgument
  132. // Parameters:
  133. // @common_ctx - process program data state context, see @sProcessProgramDataCommonContext_t
  134. // @argTypes - array of argument types to set the parameters parsing methods (see @parseArguments, @eScpiArgType_t)
  135. // Other parameters: refer @processNumericArgument
  136. // Returns: pointer to the numeric entry descriptor with value and type, and the error code, or NULL
  137. // if @common_ctx is set to NULL.
  138. const sNumericEntry_t * processArgument_Numeric_helper( void * common_ctx, const uint8_t * argTypes, const sNumericRange_t * range, uint8_t argId )
  139. {
  140. assert( common_ctx );
  141. assert( argTypes );
  142. sProcessProgramDataCommonContext_t * _common_ctx = common_ctx;
  143. if( NULL == common_ctx )
  144. {
  145. (void)_common_ctx->numericProcessContext.valueEntry.error; // inaccessible
  146. assert(false);
  147. return NULL;
  148. }
  149. else
  150. if( NULL == argTypes )
  151. {
  152. _common_ctx->numericProcessContext.valueEntry.error = ScpiNumericInvalidArg;
  153. assert(false);
  154. }
  155. else
  156. {
  157. // analyze argument type
  158. switch( argTypes[ argId ] )
  159. {
  160. case eScpiArg_Numeric:
  161. case eScpiArg_Numeric_Demical:
  162. case eScpiArg_Numeric_NonDemical:
  163. case eScpiArg_Array_Decimal:
  164. {
  165. bool state = false;
  166. sScpiParserContext_t * global_ctx = _common_ctx->global_ctx;
  167. _common_ctx->numericProcessContext.valueEntry.error = ScpiNumericInvalidArg;
  168. state = processNumericArgument( &_common_ctx->numericProcessContext,
  169. &_common_ctx->argTokens[argId],
  170. _common_ctx->argEntityTypes[argId],
  171. range );
  172. // assign current argument token (success or failed)
  173. global_ctx->sParser.xArgToken.shead = _common_ctx->argTokens[argId].shead;
  174. global_ctx->sParser.xArgToken.stail = _common_ctx->argTokens[argId].stail;
  175. if( !state )
  176. {(void)_common_ctx->numericProcessContext.valueEntry.error;}
  177. }
  178. break;
  179. default:
  180. _common_ctx->numericProcessContext.valueEntry.error = ScpiNumericInvalidArg; // invalid type
  181. assert(false);
  182. }
  183. }
  184. // error code set helper
  185. switch( _common_ctx->numericProcessContext.valueEntry.error )
  186. {
  187. case ScpiNumericSuccess:
  188. {
  189. (void)_common_ctx->status; // caller dependent
  190. }
  191. break;
  192. // "11.5.1.1.5", [1]
  193. case ScpiNumericError_DEVICE_RANGE: // the value is out of range supported by device
  194. {
  195. _common_ctx->status = eProgramDataArgumentRange; // parameter value range error, caller should generate error message
  196. }
  197. break;
  198. // "11.5.1.1.5", [1]
  199. // "10.10.6 Error Handling", [1]
  200. // "<...> An out-of-range integer shall cause an Execution Error, see 11.5.1.1.5. <...>"
  201. case ScpiNumericError_USER_RANGE: // the value is out of user specified range: // the value is out of range supported by device
  202. {
  203. _common_ctx->status = eProgramDataArgumentValue; // parameter value range error, caller should generate error message
  204. }
  205. break;
  206. case ScpiNumericError_USER_TYPE: // the value does not match to the user expectation
  207. {
  208. _common_ctx->status = eProgramDataArgumentType; // parameter type error, caller should generate error message
  209. }
  210. break;
  211. case ScpiNumericInvalidArg: assert(false); // forbidden case: design bug
  212. case ScpiNumericError: // generic numeric conversion error
  213. {
  214. _common_ctx->status = eProgramDataRuntimeError; // parameter syntax error, caller should generate error message
  215. }
  216. break;
  217. }
  218. return &_common_ctx->numericProcessContext.valueEntry;
  219. }
  220. const sNumericEntry_t * processArgument_Array_helper( void * common_ctx, const sNumericRange_t * range, uint8_t argId, void * result_arg, uint16_t result_size)
  221. {
  222. assert( common_ctx );
  223. // sProcessProgramDataCommonContext_t * _common_ctx = common_ctx;
  224. // uint16_t * _result_arg = result_arg;
  225. // for(uint8_t i = 0; i < _common_ctx->args; i++)
  226. // {
  227. // bool state = processNumericArgument( &_common_ctx->numericProcessContext,
  228. // &_common_ctx->argArray[i],
  229. // _common_ctx->argEntityTypes[0],
  230. // range );
  231. // if(state && i < result_size)
  232. // {
  233. // *_result_arg = _common_ctx->numericProcessContext.valueEntry.Value.demicalInteger;
  234. // _result_arg++;
  235. // }
  236. // else
  237. // {
  238. // _common_ctx->status = eProgramDataRuntimeError; // parameter syntax error, caller should generate error message
  239. // }
  240. // }
  241. sNumericEntry_t zagl;
  242. return &zagl;
  243. }
  244. // @scpi_argument_value_token
  245. // Get the string tokens of the specified value in the allowed CHARACTER value list.
  246. // Parameters:
  247. // @list - allowed values list, see @DECLARE_ARGUMENT_CHARACTER_ALLOWED_LIST
  248. // @valueIndex - index in the array;
  249. // @pOutToken - string token to fill, can not be NULL;
  250. // Returns: filled string token (@pOutToken).
  251. // Note: if @valueList is out of range, NULL pointer is returned, and @pOutToken is unchanged.
  252. const sStrToken_t * scpi_argument_value_token( const xArgument_t * list, size_t valueIndex, sStrToken_t * pOutToken )
  253. {
  254. if( NULL == list || NULL == pOutToken ) return NULL;
  255. // walk in the list
  256. while( (*list != NULL) && (valueIndex>0) )
  257. {
  258. valueIndex--; list++;
  259. }
  260. if( NULL == *list ) return NULL;
  261. pOutToken->shead = *list;
  262. pOutToken->stail = strlen(*list) + *list;
  263. return pOutToken;
  264. }