#define SCPI_ARGS_HELPER_C #define SCPI_CORE_PRIVATE // access to 'scpi_core_private.h' #include "app/scpi/scpi_core.h" #include "app/scpi/scpi_core_private.h" #include "app/scpi/scpi_parser.h" #include "app/scpi/scpi_commands.h" // processCharacterArgument #include "app/scpi/scpi_numeric.h" // processNumericArgument #include "app/scpi/scpi_args_helper.h" #include "app/fseq/fseq.h" // tFSeqCtx_t #include "app/scpi/CommandParserStates/process_data.h" // sProcessProgramDataCommonContext_t #include "my_assert.h" // [1] IEEE 488.2 Standard, revision IEEE Std 488.2-1987 (1992) // "IEEE Standard Codes, Formats, Protocols, and Common Commands for Use With IEEE Std 488.1-1987, IEEE // @parseArguments_helper // Helper function. Used for convenient call of @parseArguments inside command handler module // Parameters: // @common_ctx - process program data state context, see @sProcessProgramDataCommonContext_t // @argTypes - array of argument types to set the parameters parsing methods (see @parseArguments, @eScpiArgType_t) // Other parameters: refer @parseArguments // Returns: refer @parseArguments eScpiParserStatus_t parseArguments_helper( void * common_ctx, const uint8_t * argTypes, size_t argN, size_t argOptionalN) { assert( argN <= SCPI_MAX_ARGS ); sProcessProgramDataCommonContext_t * _common_ctx = common_ctx; sScpiParserContext_t * global_ctx = _common_ctx->global_ctx; // parse command parameters eScpiParserStatus_t status = parseArguments( &(global_ctx->sParser.xCtxObj), _common_ctx->argTokens, argTypes, _common_ctx->argEntityTypes, argN, argOptionalN, &_common_ctx->args ); // Modify state status value // This status can be used inside Dispatch routine of command handler _common_ctx->argsParserStatus = status; // check the parser status result if( eScpiParserStatus_success != status ) { // _common_ctx->args is index of parameter assert( _common_ctx->args < SCPI_MAX_ARGS ); // assign whole arguments chain token global_ctx->sParser.xArgToken.shead = _common_ctx->argTokens[_common_ctx->args].shead; global_ctx->sParser.xArgToken.stail = _common_ctx->argTokens[_common_ctx->args].stail; } else { // _common_ctx->args is amount of parameters assert( _common_ctx->args <= SCPI_MAX_ARGS ); // assign whole arguments chain token global_ctx->sParser.xArgToken.shead = _common_ctx->argTokens[0].shead; global_ctx->sParser.xArgToken.stail = _common_ctx->argTokens[_common_ctx->args - 1].stail; } // Reset indicator: end-of-command has been parsed _common_ctx->needParseEndOfCommand = false; return status; } // [1] IEEE 488.2 Standard, revision IEEE Std 488.2-1987 (1992) // "IEEE Standard Codes, Formats, Protocols, and Common Commands for Use With IEEE Std 488.1-1987, IEEE // @parseArrayArguments_helper // Helper function. Used for convenient call of @parseArguments inside command handler module // Parameters: // @common_ctx - process program data state context, see @sProcessProgramDataCommonContext_t // @argTypes - array of argument types to set the parameters parsing methods (see @parseArguments, @eScpiArgType_t) // Other parameters: refer @parseArguments // Returns: refer @parseArguments eScpiParserStatus_t parseArrayArguments_helper( void * common_ctx, const uint8_t * argTypes, size_t argN, size_t argOptionalN) { assert( argN <= SCPI_MAX_ARGS ); sProcessProgramDataCommonContext_t * _common_ctx = common_ctx; sScpiParserContext_t * global_ctx = _common_ctx->global_ctx; size_t argNumber = sizeof(_common_ctx->argArray)/sizeof(_common_ctx->argArray[0]); // parse command parameters eScpiParserStatus_t status = parseArrayArguments( &(global_ctx->sParser.xCtxObj), _common_ctx->argArray, &argNumber, argTypes, _common_ctx->argEntityTypes, argN, argOptionalN, &_common_ctx->args ); // Modify state status value // This status can be used inside Dispatch routine of command handler _common_ctx->argsParserStatus = status; // check the parser status result if( eScpiParserStatus_success != status ) { // _common_ctx->args is index of parameter //assert( _common_ctx->args < SCPI_MAX_ARGS ); // assign whole arguments chain token global_ctx->sParser.xArgToken.shead = _common_ctx->argTokens[_common_ctx->args].shead; global_ctx->sParser.xArgToken.stail = _common_ctx->argTokens[_common_ctx->args].stail; } else { // _common_ctx->args is amount of parameters //assert( _common_ctx->args <= SCPI_MAX_ARGS ); // assign whole arguments chain token global_ctx->sParser.xArgToken.shead = _common_ctx->argTokens[0].shead; global_ctx->sParser.xArgToken.stail = _common_ctx->argTokens[_common_ctx->args - 1].stail; } // Reset indicator: end-of-command has been parsed _common_ctx->needParseEndOfCommand = false; return status; } // @processArgument_Character_helper // Helper function. Used for convenient call of the other helper functions. // Processes the CHARACTER argument. See @processCharacterArgument // Parameters: // @common_ctx - process program data state context, see @sProcessProgramDataCommonContext_t // @argTypes - array of argument types to set the parameters parsing methods (see @parseArguments, @eScpiArgType_t) // Other parameters: refer @processCharacterArgument // Returns: SCPI_ARGUMENT_CHARACTER_INVALID_ID in error case, or argument option index in @allowedList int8_t processArgument_Character_helper( void * common_ctx, const uint8_t * argTypes, const xArgument_t * allowedList, uint8_t argId ) { assert( common_ctx ); assert( argTypes ); if( NULL == common_ctx || NULL == argTypes ) { return SCPI_ARGUMENT_CHARACTER_INVALID_ID; } assert( argTypes[ argId ] == eScpiArg_Character ); // analyze argument type if( argTypes[ argId ] != eScpiArg_Character ) { return SCPI_ARGUMENT_CHARACTER_INVALID_ID; } bool state = false; int8_t argument_idx = 0; sProcessProgramDataCommonContext_t * _common_ctx = common_ctx; sScpiParserContext_t * global_ctx = _common_ctx->global_ctx; state = processCharacterArgument( allowedList, &_common_ctx->argTokens[argId], &argument_idx ); // assign current argument token (success or failed) global_ctx->sParser.xArgToken.shead = _common_ctx->argTokens[argId].shead; global_ctx->sParser.xArgToken.stail = _common_ctx->argTokens[argId].stail; if( ! state ) { argument_idx = SCPI_ARGUMENT_CHARACTER_INVALID_ID; } return argument_idx; } // @processArgument_Numeric_helper // Helper function. Used for convenient call of the other helper functions. // Processes the NUMERIC argument. See @processNumericArgument // Parameters: // @common_ctx - process program data state context, see @sProcessProgramDataCommonContext_t // @argTypes - array of argument types to set the parameters parsing methods (see @parseArguments, @eScpiArgType_t) // Other parameters: refer @processNumericArgument // Returns: pointer to the numeric entry descriptor with value and type, and the error code, or NULL // if @common_ctx is set to NULL. const sNumericEntry_t * processArgument_Numeric_helper( void * common_ctx, const uint8_t * argTypes, const sNumericRange_t * range, uint8_t argId ) { assert( common_ctx ); assert( argTypes ); sProcessProgramDataCommonContext_t * _common_ctx = common_ctx; if( NULL == common_ctx ) { (void)_common_ctx->numericProcessContext.valueEntry.error; // inaccessible assert(false); return NULL; } else if( NULL == argTypes ) { _common_ctx->numericProcessContext.valueEntry.error = ScpiNumericInvalidArg; assert(false); } else { // analyze argument type switch( argTypes[ argId ] ) { case eScpiArg_Numeric: case eScpiArg_Numeric_Demical: case eScpiArg_Numeric_NonDemical: case eScpiArg_Array_Decimal: { bool state = false; sScpiParserContext_t * global_ctx = _common_ctx->global_ctx; _common_ctx->numericProcessContext.valueEntry.error = ScpiNumericInvalidArg; state = processNumericArgument( &_common_ctx->numericProcessContext, &_common_ctx->argTokens[argId], _common_ctx->argEntityTypes[argId], range ); // assign current argument token (success or failed) global_ctx->sParser.xArgToken.shead = _common_ctx->argTokens[argId].shead; global_ctx->sParser.xArgToken.stail = _common_ctx->argTokens[argId].stail; if( !state ) {(void)_common_ctx->numericProcessContext.valueEntry.error;} } break; default: _common_ctx->numericProcessContext.valueEntry.error = ScpiNumericInvalidArg; // invalid type assert(false); } } // error code set helper switch( _common_ctx->numericProcessContext.valueEntry.error ) { case ScpiNumericSuccess: { (void)_common_ctx->status; // caller dependent } break; // "11.5.1.1.5", [1] case ScpiNumericError_DEVICE_RANGE: // the value is out of range supported by device { _common_ctx->status = eProgramDataArgumentRange; // parameter value range error, caller should generate error message } break; // "11.5.1.1.5", [1] // "10.10.6 Error Handling", [1] // "<...> An out-of-range integer shall cause an Execution Error, see 11.5.1.1.5. <...>" case ScpiNumericError_USER_RANGE: // the value is out of user specified range: // the value is out of range supported by device { _common_ctx->status = eProgramDataArgumentValue; // parameter value range error, caller should generate error message } break; case ScpiNumericError_USER_TYPE: // the value does not match to the user expectation { _common_ctx->status = eProgramDataArgumentType; // parameter type error, caller should generate error message } break; case ScpiNumericInvalidArg: assert(false); // forbidden case: design bug case ScpiNumericError: // generic numeric conversion error { _common_ctx->status = eProgramDataRuntimeError; // parameter syntax error, caller should generate error message } break; } return &_common_ctx->numericProcessContext.valueEntry; } const sNumericEntry_t * processArgument_Array_helper( void * common_ctx, const sNumericRange_t * range, uint8_t argId, void * result_arg, uint16_t result_size) { assert( common_ctx ); // sProcessProgramDataCommonContext_t * _common_ctx = common_ctx; // uint16_t * _result_arg = result_arg; // for(uint8_t i = 0; i < _common_ctx->args; i++) // { // bool state = processNumericArgument( &_common_ctx->numericProcessContext, // &_common_ctx->argArray[i], // _common_ctx->argEntityTypes[0], // range ); // if(state && i < result_size) // { // *_result_arg = _common_ctx->numericProcessContext.valueEntry.Value.demicalInteger; // _result_arg++; // } // else // { // _common_ctx->status = eProgramDataRuntimeError; // parameter syntax error, caller should generate error message // } // } sNumericEntry_t zagl; return &zagl; } // @scpi_argument_value_token // Get the string tokens of the specified value in the allowed CHARACTER value list. // Parameters: // @list - allowed values list, see @DECLARE_ARGUMENT_CHARACTER_ALLOWED_LIST // @valueIndex - index in the array; // @pOutToken - string token to fill, can not be NULL; // Returns: filled string token (@pOutToken). // Note: if @valueList is out of range, NULL pointer is returned, and @pOutToken is unchanged. const sStrToken_t * scpi_argument_value_token( const xArgument_t * list, size_t valueIndex, sStrToken_t * pOutToken ) { if( NULL == list || NULL == pOutToken ) return NULL; // walk in the list while( (*list != NULL) && (valueIndex>0) ) { valueIndex--; list++; } if( NULL == *list ) return NULL; pOutToken->shead = *list; pOutToken->stail = strlen(*list) + *list; return pOutToken; }