search_for_command.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. #define SCPI_CORE_STATE__SEARCH4COMMAND_GUARD
  2. #include "app/scpi/CommandParserStates/search_for_command.h"
  3. #define SCPI_CORE_PRIVATE // access to 'scpi_core_private.h'
  4. #include "app/scpi/scpi_core_private.h"
  5. // =================================================================================
  6. // @sSearchForCommandHeaderContext_t
  7. // State's private context typedef
  8. typedef struct
  9. {
  10. bool bKeepParserContext;
  11. }
  12. sSearchForCommandHeaderContext_t;
  13. // =================================================================================
  14. // @ctx_SearchForCommandHeader
  15. // State's private context
  16. sSearchForCommandHeaderContext_t ctx_SearchForCommandHeader;
  17. // =================================================================================
  18. // @fsqvbl_SearchForCommandHeader
  19. // State's virtual table
  20. static void fsqe_SearchForCommandHeader( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx );
  21. static void fsql_SearchForCommandHeader( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx );
  22. static const struct fFSeqEntry_t * fsqf_SearchForCommandHeader( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx, const struct fFSeqEntry_t * * pnext );
  23. const fFSeqVTable_t fsqvbl_SearchForCommandHeader =
  24. {
  25. .f = fsqf_SearchForCommandHeader,
  26. .enter = fsqe_SearchForCommandHeader,
  27. .leave = fsql_SearchForCommandHeader
  28. };
  29. // =================================================================================
  30. // @fsqe_SearchForCommandHeader
  31. // State's enter routine
  32. static void fsqe_SearchForCommandHeader( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx )
  33. {
  34. sScpiParserContext_t * global_ctx = ctx;
  35. sSearchForCommandHeaderContext_t * private_ctx = fsq_GetPrivateCtxRef(this);
  36. private_ctx->bKeepParserContext = false;
  37. (void)global_ctx;
  38. }
  39. // =================================================================================
  40. // @fsql_SearchForCommandHeader
  41. // State's leave routine
  42. static void fsql_SearchForCommandHeader( const struct fFSeqEntry_t * this, tFSeqCtx_t ctx )
  43. {
  44. sScpiParserContext_t * global_ctx = ctx;
  45. sSearchForCommandHeaderContext_t * private_ctx = fsq_GetPrivateCtxRef(this);
  46. (void)ctx, (void)private_ctx;
  47. (void)global_ctx;
  48. }
  49. // =================================================================================
  50. // @fsqf_SearchForCommandHeader
  51. // State's body routine
  52. static const struct fFSeqEntry_t * fsqf_SearchForCommandHeader( const struct fFSeqEntry_t * this,
  53. tFSeqCtx_t ctx,
  54. const struct fFSeqEntry_t * * pDeferredNext )
  55. {
  56. // --------------------------------------------------------------------------
  57. const struct fFSeqEntry_t * nextstate = NULL; // do not change state, do not call next state
  58. sScpiParserContext_t * global_ctx = ctx;
  59. sSearchForCommandHeaderContext_t * private_ctx = fsq_GetPrivateCtxRef(this);
  60. // --------------------------------------------------------------------------
  61. // Handle events:
  62. switch( global_ctx->sEvent.eCode )
  63. {
  64. case eScpiEventRestart:
  65. {
  66. nextstate = fsq_GetStateById(this,eParserResetState);
  67. }
  68. break;
  69. case eScpiEventWrite: // Handle the WRITE event
  70. case eScpiEventRead: // Handle the READ event
  71. {
  72. // prepare parser context
  73. if( !prepareParserContext( &(global_ctx->sParser.xCtxObj),
  74. global_ctx->sMessage.pStr, // pass input buffer
  75. (ptrdiff_t)global_ctx->sMessage.pEnd - (ptrdiff_t)global_ctx->sMessage.pStr, // pass input buffer size
  76. global_ctx->sMessage.w_bEndOfMessage, // pass end-of-message by identifying the event
  77. private_ctx->bKeepParserContext ) )
  78. {
  79. global_ctx->sEvent.eStatus = eScpiStatus_invalid;
  80. }
  81. else
  82. {
  83. // parse the command program header
  84. global_ctx->sEvent.eStatus = parseCommandProgramHeader( &(global_ctx->sParser.xCtxObj) );
  85. switch( global_ctx->sEvent.eStatus )
  86. {
  87. case eScpiStatus_success:
  88. {
  89. // successfully parsed
  90. // go to next state: eProcessCommandHeader
  91. nextstate = fsq_GetStateById(this,eProcessCommandHeader);
  92. }
  93. break;
  94. case eScpiStatus_need_data:
  95. {
  96. private_ctx->bKeepParserContext = true;
  97. (void)nextstate; // keep NULL, do not change state
  98. }
  99. break;
  100. case eScpiStatus_failed:
  101. case eScpiStatus_invalid:
  102. {
  103. const char * start = NULL;
  104. const char * stop = NULL;
  105. uint8_t type;
  106. if( getParsedEntityDetails( &(global_ctx->sParser.xCtxObj), (const void**)&start, (const void**)&stop, &type ) )
  107. {
  108. // check for empty-line command string
  109. if( scpi_isnl(*start) )
  110. {
  111. // requested string is an empty-line command string, and the parser error is obviously can not be generated
  112. // But it is required to enter the error state because only the error state is legal next state.
  113. // It is impossible to restart the parser because maybe there are some data in output buffer to sent.
  114. }
  115. else
  116. {
  117. // Check if the last character is '\n' and cut it off
  118. if( scpi_isnl((*(stop-1))) && (0 < (stop - start)) ) stop--;
  119. int32_t error;
  120. const char * msg = getParserError( &(global_ctx->sParser.xCtxObj), &error );
  121. if( NULL == msg )
  122. {
  123. error = SCPI_ERROR_COMMAND_HEADER;
  124. msg = SCPI_ERROR_COMMAND_HEADER_MSG;
  125. }
  126. fsq_RaiseError( error, msg, start, stop );
  127. }
  128. }
  129. else
  130. {
  131. #if 0
  132. int32_t error;
  133. const char * msg = getParserError( &(global_ctx->sParser.xCtxObj), &error );
  134. if( NULL == msg )
  135. {
  136. error = SCPI_ERROR_COMMAND_HEADER;
  137. msg = SCPI_ERROR_COMMAND_HEADER_MSG;
  138. }
  139. fsq_RaiseError( error, msg, NULL, 0 );
  140. #else
  141. assert( false );
  142. #endif
  143. }
  144. nextstate = fsq_GetStateById(this,eHandleError); // enter the error state
  145. }
  146. break;
  147. }
  148. }
  149. }
  150. break;
  151. case eScpiEventError: // Transport error.
  152. {
  153. // Enter error state
  154. nextstate = fsq_GetStateById(this,eHandleError); // enter the error state
  155. }
  156. break;
  157. }
  158. (void)global_ctx->sEvent.eCode; // keep event code, it will be reused in @eProcessProgramData state
  159. return nextstate;
  160. }