scpi_parser.h 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633
  1. #ifndef SCPI_PARSER_H
  2. #define SCPI_PARSER_H
  3. #include <stdint.h>
  4. #include <stddef.h>
  5. #include "my_assert.h"
  6. #include <stdbool.h>
  7. #include <string.h>
  8. #include "app/scpi/scpi_base.h" // eScpiParserStatus_t
  9. #include "app/scpi/scpi_errs.h"
  10. // SCPI Parser functions
  11. // Author: Sychov A., 01/aug/2019
  12. //----------------------------------------------------------------
  13. // Refer to:
  14. // [1] IEEE 488.2 Standard, revision IEEE Std 488.2-1987 (1992)
  15. // "IEEE Standard Codes, Formats, Protocols, and Common Commands for Use With IEEE Std 488.1-1987, IEEE
  16. // Standard Digital Interface for Programmable Instrumentation"
  17. // [2] SCPI Specification, revision 1999.0
  18. // "Standard Commands for Programmable Instruments (SCPI), VERSION 1999.0, May 1999"
  19. //----------------------------------------------------------------
  20. #define SCPI_CHARACTER_COMMON_HEADER '*'
  21. #define SCPI_CHARACTER_MESSAGE_SEPARATOR ';'
  22. #define SCPI_CHARACTER_RESPONSE_SEPARATOR ';'
  23. #define SCPI_CHARACTER_COMPOUNDCOMMAND_SEPARATOR ':'
  24. #define SCPI_CHARACTER_WHITE ' '
  25. #define SCPI_CHARACTER_NL '\n'
  26. #define SCPI_CHARACTER_DATA_SEPARATOR ','
  27. #define SCPI_CHARACTER_QUERY '?'
  28. #define SCPI_CHARACTER_DEFNODE_OPEN '['
  29. #define SCPI_CHARACTER_DEFNODE_CLOSE ']'
  30. #define SCPI_CHARACTER_BRK_OPEN '('
  31. #define SCPI_CHARACTER_BRK_CLOSE ')'
  32. // ==============================================================================================
  33. // @xParseEntry_t
  34. // The parser-function context.
  35. // User shall prepare the context by calling
  36. // ... @prepareParserContext function before
  37. // ... calling any parser-function.
  38. typedef struct
  39. {
  40. const void * private[15]; // private fields, shall not be accessed by user
  41. }
  42. xParseEntry_t;
  43. // ==============================================================================================
  44. // @eScpiParserStatus_t
  45. // Parser-functions returns statuses:
  46. typedef enum
  47. {
  48. eScpiParserStatus__min = -2147483648, // don't care, just makes the enum to take 4 bytes
  49. // ------------------------------------------------------------------------------------------
  50. // Error statuses:
  51. eScpiParserStatus_invalid = eScpiStatus_invalid,
  52. // Invalid argument value: the context have not changed.
  53. // User shall check the input parameters and repeat.
  54. // User shall not prepare the context before repeated call.
  55. eScpiParserStatus_failed = eScpiStatus_failed,
  56. // Can not parse element, but the context have changed.
  57. // The element can not be parsed due to either wrong
  58. // ... format or some error during processing.
  59. // User shall not interpretate any results stored in the
  60. // ... context. User shall prepare the context before
  61. // ... next call of any parser-function with specifying
  62. // ... @bKeepContext value as 'false'.
  63. // Success status:
  64. eScpiParserStatus_success = eScpiStatus_success,
  65. // The element successfully parsed and the context have changed.
  66. // User can get detailed information from the context.
  67. // User shall prepare the context before next call of any
  68. // ... parser-function with specifying@bKeepContext value
  69. // ... as 'false'.
  70. // Warning status:
  71. eScpiParserStatus_need_data = eScpiStatus_need_data,
  72. // Need more data to continue, the context have changed.
  73. // The function can not process whole element in the buffer
  74. // ... due to not enough data stored in the buffer. User
  75. // ... shall continue processing as soon as get more data.
  76. // Note: even to continue user must prepare context and
  77. // ... specify @bKeepContext as 'true' value.
  78. // ------------------------------------------------------------------------------------------
  79. eScpiParserStatus__max = 2147483647 // don't care, just makes the enum to take 4 bytes
  80. }
  81. eScpiParserStatus_t;
  82. // ==============================================================================================
  83. #pragma pack( push, 1 )
  84. // @eScpiEntityType_t
  85. // SCPI PROGRAM MESSAGE element types, refer to "7.3.3 Functional Element Summary", [1]
  86. typedef enum
  87. {
  88. eScpiEntityType__min = 0,
  89. // ------------------------------
  90. eScpiEntityTypeInvalid = 0, // entity type is undefined (default value)
  91. eScpiEntityTypeString, // IEEE 488.2 String, "<STRING PROGRAM DATA> 7.7.5", [1]
  92. eScpiEntityTypeArbitraryBlock, // IEEE 488.2 Arbitrary Block, "7.7.6 <ARBITRARY BLOCK PROGRAM DATA>", [1]
  93. eScpiEntityTypeProgramMnemonic, // IEEE 488.2 Program Mnemonic, "7.6.1.2 Encoding Syntax", [1]
  94. eScpiEntityTypeCharacter, // IEEE 488.2 Character, "7.7.1 <CHARACTER PROGRAM DATA>", [1]
  95. eScpiEntityTypeCmnCommandProgHdr, // IEEE 488.2 Common Command Program Header, "7.6.1 <COMMAND PROGPRAM HEADER>", [1]
  96. eScpiEntityTypeCmnQueryProgHdr, // IEEE 488.2 Common Query Program Header, "7.6.2 <QUERY PROGPRAM HEADER>", [1]
  97. eScpiEntityTypeCmpCommandProgHdr, // IEEE 488.2 Compound/Simple Command Program Header, "7.6.1 <COMMAND PROGPRAM HEADER>", [1]
  98. eScpiEntityTypeCmpQueryProgHdr, // IEEE 488.2 Compound/Simple Query Program Header, "7.6.2 <QUERY PROGPRAM HEADER>", [1]
  99. eScpiEntityTypeDemicalFloatNumber,// IEEE 488.2 Demical Number (float, only mantissa), "7.7.2 <DECIMAL NUMERIC PROGRAM DATA>", [1]
  100. eScpiEntityTypeDemicalExpNumber, // IEEE 488.2 Demical Number (scientific, mantissa+exponent), "7.7.2 <DECIMAL NUMERIC PROGRAM DATA>", [1]
  101. eScpiEntityTypeHexNumber, // IEEE 488.2 Hexademical Number, "7.7.4 <NONDECIMAL NUMERIC PROGRAM DATA>", [1]
  102. eScpiEntityTypeOctNumber, // IEEE 488.2 Octal Number, "7.7.4 <NONDECIMAL NUMERIC PROGRAM DATA>", [1]
  103. eScpiEntityTypeBinNumber, // IEEE 488.2 Binary Number, "7.7.4 <NONDECIMAL NUMERIC PROGRAM DATA>", [1]
  104. eScpiEntityTypeDemicalIntegerNumber, // Integer number only, extension for IEEE 488.2 Demical Number "7.7.2 <DECIMAL NUMERIC PROGRAM DATA>", [1]
  105. // ------------------------------
  106. eScpiEntityType_Service_Invalid = 128,
  107. // ------------------------------
  108. eScpiEntityType_Service_MsgTerm, // IEEE 488.2 Message terminator, "7.5 <PROGRAM MESSAGE TERMINATOR>, [1]"
  109. eScpiEntityType_Service_MsgSep, // IEEE 488.2 Message separator, "7.4.1 <PROGRAM MESSAGE UNIT SEPARATOR>, [1]"
  110. eScpiEntityType_Service_HdrSep, // IEEE 488.2 Header separator, "7.4.3 <PROGRAM HEADER SEPARATOR>, [1]"
  111. eScpiEntityType_Service_DataSep, // IEEE 488.2 Data separator, "7.4.2 <PROGRAM DATA SEPARATOR>, [1]"
  112. eScpiEntityType_Service_White, // IEEE 488.2 Data separator, "7.4.1.2 <WHITE CHARACTER>, [1]"
  113. // ------------------------------
  114. eScpiEntityType__max = 255,
  115. }
  116. eScpiEntityType_t;
  117. #pragma pack( pop )
  118. // ==============================================================================================
  119. #pragma pack( push, 1 )
  120. // @eScpiArgType_t
  121. // SCPI command argument type for @parseArgument routine
  122. typedef enum
  123. {
  124. eScpiArg_No_Args, // Invalid value
  125. eScpiArg_Character, // - parseCharacter
  126. eScpiArg_String, // - parseString
  127. eScpiArg_Datablock, // - parseArbitraryBlock
  128. eScpiArg_Numeric, // - parseDemicalNumber + parseNonDemicalNumber (not supported)
  129. eScpiArg_Numeric_Demical, // - parseDemicalNumber
  130. eScpiArg_Numeric_NonDemical, // - parseNonDemicalNumber
  131. eScpiArg_Array_Decimal, // - parseDecimalArray
  132. // ------------------------------
  133. eScpiArg__max = 255,
  134. }
  135. eScpiArgType_t;
  136. #pragma pack( pop )
  137. // ==============================================================================================
  138. // @prepareParserContext
  139. // Preapres a parser context @xObj before a parser-function call.
  140. // The function must be called before each call of any parser-function.
  141. // If it is required to call the parser function multiple times, user
  142. // ... shall analyze the last return status and specify the @bKeepContext
  143. // ... parameter to the corresponding value. See also @eScpiParserStatus_t.
  144. // Parameters:
  145. // @xObj - the parse context to prepare;
  146. // @pBuffer - the memory buffer containing the SCPI element to be parsed;
  147. // @length - the memory buffer length;
  148. // @bEndMessage - specifies if the specified buffer holds a complete
  149. // ... message or not. If the @pBuffer contains a portion of received
  150. // ... data and there no information about the whole message length,
  151. // ... the @bEndMessage value must be 'false'. Otherwise, if known that
  152. // ... the buffer contains the final portion of data (even inclidung the
  153. // ... terminating characters), the value must be 'true'.
  154. // @bKeepContext - specifies if it is required to cleanup the context
  155. // ... to restart the parsing ('false'), or it is required to keep the
  156. // ... context to continue ('true').
  157. // Returns: 'true' in success case,
  158. // 'false' otherwise.
  159. // Note in case the function returns 'false' user must not use the
  160. // ... @xObj context due to it is still not prepared.
  161. bool prepareParserContext( xParseEntry_t * xObj, const void * pBuffer, size_t length,
  162. bool bEndMessage, bool bKeepContext );
  163. // ==============================================================================================
  164. // @getParsedEntityDetails
  165. // Retrieves the parsing results from the parser context.
  166. // The function shall not be called until either the
  167. // ... @eScpiParserStatus_success status or @eScpiParserStatus_need_data
  168. // ... are returned by last parser-function call.
  169. // Note: take in account, that in case @eScpiParserStatus_need_data had
  170. // ... been returned during the last parser-function call, the @eEntityType
  171. // ... will be set to @eScpiEntityTypeInvalid due to the entity is still
  172. // ... not identified (need more data).
  173. // Parameters:
  174. // @xObj - the parser context to get results from;
  175. // @pxEntityBegin - pointer to the pointer-variable to store the
  176. // ... parsed entity beginning, can be NULL;
  177. // @pxEntityEnd - pointer to the pointer-variable to store the
  178. // ... parsed entity ending, can be NULL;
  179. // @peEntityType - pointer to the uint8-variable to store the
  180. // ... parsed entity type, the type is encoded as described
  181. // ... in @eScpiEntityType_t enum, can be NULL;
  182. // Note: in case the parameters described above are NULL an appropriate
  183. // ... information will not be returned and can be retrieved by
  184. // ... another call of this function with non-NULL argument until
  185. // ... the @prepareParserContext is called for the specified context.
  186. // Returns: 'true' in success case,
  187. // 'false' otherwise.
  188. bool getParsedEntityDetails( const xParseEntry_t * xObj,
  189. const void * * pxEntityBegin,
  190. const void * * pxEntityEnd,
  191. uint8_t * peEntityType );
  192. // ==============================================================================================
  193. // @getParserError
  194. // Retrieves the last parser error code and message
  195. // The function shall not be called until either the @eScpiParserStatus_failed status
  196. // is returned by last parser-function call.
  197. // @xObj - the parser context to get results from;
  198. // @pErrorCode - optional pointer to the variable to store the error code, can be NULL;
  199. // Returns:
  200. // The parser error message string. Use @getParsedEntityDetails to retrieve more details.
  201. // Possible values:
  202. // - NULL: no error occurred in specified context or invalid context;
  203. // - non-null: valid constant null-terminated string message, no memory free is required;
  204. const char * getParserError( const xParseEntry_t * xObj,
  205. int32_t * pErrorCode );
  206. // =================================================================================================================
  207. // @setParserError
  208. // Assigne the last parser error code and message
  209. // The function shall not be called after calling any parser function that return error
  210. // status code to prevent overwriting actual error code and description.
  211. // @xObj - the parser context to get results from;
  212. // @errorCode - SCPI Error code, [2]
  213. // @pErrorDesc - Error description, constant null-terminated string;
  214. // Returns:
  215. // true - successful operation,
  216. // false - failed
  217. bool setParserError( const xParseEntry_t * xObj,
  218. int32_t errorCode,
  219. const char * pErrorDesc );
  220. // ==============================================================================================
  221. // @parseArbitraryBlock
  222. // "Parser-function", parses an arbitrary block (ARBITRARY BLOCK PROGRAM DATA)
  223. // References:
  224. // "7.7.6 <ARBITRARY BLOCK PROGRAM DATA>", [1]
  225. // "7.7.6.2 Encoding Syntax", [1]
  226. // Parameters:
  227. // @xObj - parser context, must be prepared by @prepareParserContext
  228. // ... before each call. If it is needed to continue the processing, the
  229. // ... @bKeepContext parameter duing the call @prepareParserContext must
  230. // ... be set to 'true', and otherwise, to restart parsing the parameter
  231. // ... must be set to 'false'.
  232. // Returns:
  233. // eScpiParserStatus_failed - error, can not parse data as a string;
  234. // eScpiParserStatus_success - success, the string has been successfully parsed;
  235. // eScpiParserStatus_need_data - warning, the string can not be parsed due to
  236. // there no enough data to process.
  237. eScpiParserStatus_t parseArbitraryBlock( xParseEntry_t * xObj );
  238. // ==============================================================================================
  239. // @parseString
  240. // "Parser-function", parses a SCPI string (STRING PROGRAM DATA)
  241. // References:
  242. // "<STRING PROGRAM DATA> 7.7.5", [1]
  243. // "7.7.5.2 Encoding Syntax", [1]
  244. // Parameters:
  245. // @xObj - parser context, must be prepared by @prepareParserContext
  246. // ... before each call. If it is needed to continue the processing, the
  247. // ... @bKeepContext parameter duing the call @prepareParserContext must
  248. // ... be set to 'true', and otherwise, to restart parsing the parameter
  249. // ... must be set to 'false'.
  250. // Returns:
  251. // eScpiParserStatus_failed - error, can not parse data as a string;
  252. // eScpiParserStatus_success - success, the string has been successfully parsed;
  253. // eScpiParserStatus_need_data - warning, the string can not be parsed due to
  254. // there no enough data to process.
  255. eScpiParserStatus_t parseString( xParseEntry_t * xObj );
  256. // =================================================================================================================
  257. // @parseCharacter
  258. // "Parser-function", parses a SCPI character (CHARACTER PROGRAM DATA)
  259. // References:
  260. // "7.7.1 <CHARACTER PROGRAM DATA>", [1]
  261. // "7.7.1.2 Encoding Syntax", [1]
  262. // Parameters:
  263. // @xObj - parser context, must be prepared by @prepareParserContext
  264. // ... before each call. If it is needed to continue the processing, the
  265. // ... @bKeepContext parameter duing the call @prepareParserContext must
  266. // ... be set to 'true', and otherwise, to restart parsing the parameter
  267. // ... must be set to 'false'.
  268. // Returns:
  269. // eScpiParserStatus_failed - error, can not parse data as a string;
  270. // eScpiParserStatus_success - success, the string has been successfully parsed;
  271. // eScpiParserStatus_need_data - warning, the string can not be parsed due to
  272. // there no enough data to process.
  273. eScpiParserStatus_t parseCharacter( xParseEntry_t * xObj );
  274. // ==============================================================================================
  275. // @parseProgramMenmonic
  276. // "Parser-function", parses a SCPI Program Mnemonic (<program mnemonic>)
  277. // References:
  278. // "<program mnemonic>", "7.6.1.2 Encoding Syntax", [1]
  279. // Parameters:
  280. // @xObj - parser context, must be prepared by @prepareParserContext
  281. // ... before each call. If it is needed to continue the processing, the
  282. // ... @bKeepContext parameter duing the call @prepareParserContext must
  283. // ... be set to 'true', and otherwise, to restart parsing the parameter
  284. // ... must be set to 'false'.
  285. // Returns:
  286. // eScpiParserStatus_failed - error, can not parse data as a string;
  287. // eScpiParserStatus_success - success, the string has been successfully parsed;
  288. // eScpiParserStatus_need_data - warning, the string can not be parsed due to
  289. // there no enough data to process.
  290. eScpiParserStatus_t parseProgramMenmonic( xParseEntry_t * xObj );
  291. // ==============================================================================================
  292. // @parseCharacter
  293. // "Parser-function", parses a SCPI character (CHARACTER PROGRAM DATA)
  294. // References:
  295. // "7.7.1 <CHARACTER PROGRAM DATA>", [1]
  296. // "7.7.1.2 Encoding Syntax", [1]
  297. // Parameters:
  298. // @xObj - parser context, must be prepared by @prepareParserContext
  299. // ... before each call. If it is needed to continue the processing, the
  300. // ... @bKeepContext parameter duing the call @prepareParserContext must
  301. // ... be set to 'true', and otherwise, to restart parsing the parameter
  302. // ... must be set to 'false'.
  303. // Returns:
  304. // eScpiParserStatus_failed - error, can not parse data as a string;
  305. // eScpiParserStatus_success - success, the string has been successfully parsed;
  306. // eScpiParserStatus_need_data - warning, the string can not be parsed due to
  307. // there no enough data to process.
  308. eScpiParserStatus_t parseCharacter( xParseEntry_t * xObj );
  309. // ==============================================================================================
  310. // @parseCommandProgramHeader
  311. // "Parser-function", parses a SCPI Command/Query Program Header (<COMMAND PROGRAM HEADER>, <QUERY PROGRMA HEADER>)
  312. // References:
  313. // "7.6.1 <COMMAND PROGPRAM HEADER>", [1]
  314. // "7.6.1.2 Encoding Syntax", [1]
  315. // "7.6.2 <COMMAND PROGPRAM HEADER>", [1]
  316. // "7.6.2.2 Encoding Syntax", [1]
  317. // Parameters:
  318. // @xObj - parser context, must be prepared by @prepareParserContext
  319. // ... before each call. If it is needed to continue the processing, the
  320. // ... @bKeepContext parameter duing the call @prepareParserContext must
  321. // ... be set to 'true', and otherwise, to restart parsing the parameter
  322. // ... must be set to 'false'.
  323. // Returns:
  324. // eScpiParserStatus_failed - error, can not parse data as a string;
  325. // eScpiParserStatus_success - success, the string has been successfully parsed;
  326. // eScpiParserStatus_need_data - warning, the string can not be parsed due to
  327. // ... there no enough data to process.
  328. // Notes: All white spaces before the found command program header is skipped,
  329. // ... the @pxEntityBegin parameter during @getParsedEntityDetails call will refer
  330. // ... to the command program header beginning.
  331. eScpiParserStatus_t parseCommandProgramHeader( xParseEntry_t * xObj );
  332. // =================================================================================================================
  333. // @parseNumber
  334. // "Parser-function", parses a SCPI Demical Numeric Program Data and SCPI Hexademical/Octal/Binary Numeric Program Data
  335. // References:
  336. // "7.7.2 <DECIMAL NUMERIC PROGRAM DATA>", [1]
  337. // "7.7.2.2 Encoding Syntax", [1]
  338. // "7.7.4 <NONDECIMAL NUMERIC PROGRAM DATA>", [1]
  339. // "7.7.4.2 Encoding Syntax", [1]
  340. // Parameters:
  341. // @xObj - parser context, must be prepared by @prepareParserContext
  342. // ... before each call. If it is needed to continue the processing, the
  343. // ... @bKeepContext parameter duing the call @prepareParserContext must
  344. // ... be set to 'true', and otherwise, to restart parsing the parameter
  345. // ... must be set to 'false'.
  346. // Returns:
  347. // eScpiParserStatus_failed - error, can not parse data;
  348. // eScpiParserStatus_success - success, the string has been successfully parsed;
  349. // eScpiParserStatus_need_data - warning, the string can not be parsed due to
  350. // there no enough data to process.
  351. eScpiParserStatus_t parseNumber( xParseEntry_t * xObj );
  352. // ==============================================================================================
  353. // @parseProgramDataSeparator
  354. // "Parser-function", parses a SCPI Program Data Separator
  355. // References:
  356. // "7.4 Separator Functional Elements", [1]
  357. // "7.4.2.2 Encoding Syntax", [1]
  358. // Parameters:
  359. // @xObj - parser context, must be prepared by @prepareParserContext
  360. // ... before each call. If it is needed to continue the processing, the
  361. // ... @bKeepContext parameter duing the call @prepareParserContext must
  362. // ... be set to 'true', and otherwise, to restart parsing the parameter
  363. // ... must be set to 'false'.
  364. // Returns:
  365. // eScpiParserStatus_failed - error, can not parse data as a string;
  366. // eScpiParserStatus_success - success, the string has been successfully parsed;
  367. // eScpiParserStatus_need_data - warning, the string can not be parsed due to
  368. // there no enough data to process.
  369. eScpiParserStatus_t parseProgramDataSeparator( xParseEntry_t * xObj );
  370. // =================================================================================================================
  371. // @parseProgramDataSeparator
  372. // "Parser-function", parses a SCPI Program Header Separator
  373. // References:
  374. // "7.4.3 <PROGRAM HEADER SEPARATOR>, [1]
  375. // "7.4.3.2 Encoding Syntax", [1]
  376. // "7.5 <PROGRAM MESSAGE TERMINATOR>", [1]
  377. // Parameters:
  378. // @xObj - parser context, must be prepared by @prepareParserContext
  379. // ... before each call. If it is needed to continue the processing, the
  380. // ... @bKeepContext parameter duing the call @prepareParserContext must
  381. // ... be set to 'true', and otherwise, to restart parsing the parameter
  382. // ... must be set to 'false'.
  383. // Returns:
  384. // eScpiParserStatus_failed - error, can not parse data as a string;
  385. // eScpiParserStatus_success - success, the string has been successfully parsed;
  386. // eScpiParserStatus_need_data - warning, the string can not be parsed due to
  387. // there no enough data to process.
  388. eScpiParserStatus_t parseProgramHeaderSeparator( xParseEntry_t * xObj );
  389. // =================================================================================================================
  390. // @parseProgramMessageSeparator
  391. // "Parser-function", parses a SCPI Program Message Separator
  392. // References:
  393. // "7.4.1 <PROGRAM MESSAGE UNIT SEPARATOR>", [1]
  394. // "7.4.1.2 Encoding Syntax", [1]
  395. // "7.5 <PROGRAM MESSAGE TERMINATOR>", [1]
  396. // Parameters:
  397. // @xObj - parser context, must be prepared by @prepareParserContext
  398. // ... before each call. If it is needed to continue the processing, the
  399. // ... @bKeepContext parameter duing the call @prepareParserContext must
  400. // ... be set to 'true', and otherwise, to restart parsing the parameter
  401. // ... must be set to 'false'.
  402. // Returns:
  403. // eScpiParserStatus_failed - error, can not parse data as a string;
  404. // eScpiParserStatus_success - success, the string has been successfully parsed;
  405. // eScpiParserStatus_need_data - warning, the string can not be parsed due to
  406. // there no enough data to process.
  407. eScpiParserStatus_t parseProgramMessageSeparator( xParseEntry_t * xObj );
  408. // @parseEndOfCommand
  409. // "Parser-function", searches end of program command unit.
  410. // References:
  411. // "7.4.1 <PROGRAM MESSAGE UNIT SEPARATOR>", [1]
  412. // "7.4.1.2 Encoding Syntax", [1]
  413. // "7.5 <PROGRAM MESSAGE TERMINATOR>", [1]
  414. // Parameters:
  415. // @xObj - parser context, must be prepared by @prepareParserContext
  416. // ... before each call. If it is needed to continue the processing, the
  417. // ... @bKeepContext parameter duing the call @prepareParserContext must
  418. // ... be set to 'true', and otherwise, to restart parsing the parameter
  419. // ... must be set to 'false'.
  420. // Returns:
  421. // eScpiParserStatus_failed - error, can not parse data as a string;
  422. // eScpiParserStatus_success - success, the string has been successfully parsed;
  423. // eScpiParserStatus_need_data - warning, the string can not be parsed due to
  424. // there no enough data to process.
  425. eScpiParserStatus_t parseEndOfCommand( xParseEntry_t * xObj );
  426. // ==============================================================================================
  427. // @scpi_iscmdsep
  428. // Detects if the passed character @ch is a SCPI Program Header Mnemonic Separator
  429. // Refer to:
  430. // "7.6.1 <COMMAND PROGPRAM HEADER>", [1]
  431. // "7.6.1.5 Header Compounding Rules", [1]
  432. // "7.6.2 <QUERY PROGRAM HEADER>", [1]
  433. // "7.6.2.2 Encoding Syntax", [1]
  434. static inline bool scpi_iscmdsep( char ch )
  435. {
  436. return ( SCPI_CHARACTER_COMPOUNDCOMMAND_SEPARATOR == ch );
  437. }
  438. // ==============================================================================================
  439. // @scpi_iswhite
  440. // Detects if the passed character @ch is a SCPI White Character
  441. // Refer to:
  442. // "7.4 Separator Functional Elements", [1]
  443. // "7.4.1.2 Encoding Syntax", [1]
  444. static inline bool scpi_iswhite( char ch )
  445. {
  446. return ( ch <= SCPI_CHARACTER_WHITE && ch != SCPI_CHARACTER_NL ); // 7.4.1.2 Encoding Syntax, [1]
  447. }
  448. // ==============================================================================================
  449. // @scpi_isdatasep
  450. // Detects if the passed character @ch is a SCPI Program Data Separator
  451. // Refer to:
  452. // "7.4 Separator Functional Elements", [1]
  453. // "7.4.2.2 Encoding Syntax", [1]
  454. static inline bool scpi_isdatasep( char ch )
  455. {
  456. return ( SCPI_CHARACTER_DATA_SEPARATOR == ch ); // 7.4.2.2 Encoding Syntax, [1]
  457. }
  458. // ==============================================================================================
  459. // @scpi_ismsgsep
  460. // Detects if the passed character @ch is a SCPI Program Message Separator
  461. // Refer to:
  462. // "7.4 Separator Functional Elements", [1]
  463. // "7.4.1.2 Encoding Syntax", [1]
  464. static inline bool scpi_ismsgsep( char ch )
  465. {
  466. return ( SCPI_CHARACTER_MESSAGE_SEPARATOR == ch ); // 7.4.1.2 Encoding Syntax, [1]
  467. }
  468. // ==============================================================================================
  469. // @scpi_isnl
  470. // Detects if the passed character @ch is a SCPI NL Character (New Line)
  471. // Refer to:
  472. // "7.5 <PROGRAM MESSAGE TERMINATOR>", [1]
  473. // "7.5.2 Encoding Syntax", [1]
  474. static inline bool scpi_isnl( char ch )
  475. {
  476. return ( ch == SCPI_CHARACTER_NL ); // 7.5.2 Encoding Syntax, [1]
  477. }
  478. // ==============================================================================================
  479. // @scpi_queryind
  480. // Detects if the passed character @ch is a SCPI Query Indicator
  481. // Refer to:
  482. // "6.1.6.2.3 Query Detected Message (query)", [1]
  483. // "7.6.2.2 Encoding Syntax", [1]
  484. static inline bool scpi_queryind( char ch )
  485. {
  486. return ( ch == SCPI_CHARACTER_QUERY ); // 7.6.2.2 Encoding Syntax, [1]
  487. }
  488. // ==============================================================================================
  489. // @scpi_commonhdrind
  490. // Detects if the passed character @ch is a SCPI Common Program Header indicator
  491. // Refer to:
  492. // "7.6.1.2 Encoding Syntax", [1]
  493. static inline bool scpi_commonhdrind( char ch )
  494. {
  495. return ( ch == SCPI_CHARACTER_COMMON_HEADER ); // 7.6.1.2 Encoding Syntax, [1]
  496. }
  497. // ==============================================================================================
  498. // @scpi_cmdsep
  499. // Search for the command mnemonic separator
  500. // @cmdheader - null-terminated string containing simple or
  501. // ... compound SCPI command program header.
  502. // See ("7.6.1 <COMMAND PROGPRAM HEADER>", [1])
  503. // Note: routine modified in order to detect end of line
  504. static inline const char * scpi_cmdsep( const char * cmdheader )
  505. {
  506. assert( cmdheader );
  507. while( '\0' != *cmdheader
  508. && !scpi_isnl( *cmdheader)
  509. && !scpi_iscmdsep(*cmdheader)
  510. && !scpi_iswhite(*cmdheader)
  511. && !scpi_ismsgsep(*cmdheader) )
  512. cmdheader++;
  513. return cmdheader;
  514. }
  515. // ==============================================================================================
  516. // @scpi_isopt_open
  517. // Detects if the passed character @ch is a SCPI Opening Default Mnemonic Encoding character
  518. // Refer to:
  519. // "5.1 Interpreting Command Tables", [2]
  520. static inline bool scpi_isopt_open( char ch )
  521. {
  522. return ( ch == SCPI_CHARACTER_DEFNODE_OPEN );
  523. }
  524. // ==============================================================================================
  525. // @scpi_isopt_close
  526. // Detects if the passed character @ch is a SCPI Opening Default Mnemonic Encoding character
  527. // Refer to:
  528. // "5.1 Interpreting Command Tables", [2]
  529. static inline bool scpi_isopt_close( char ch )
  530. {
  531. return ( ch == SCPI_CHARACTER_DEFNODE_CLOSE );
  532. }
  533. // =================================================================================================================
  534. // @parseWhiteSequence
  535. // "Parser-function", searches for white characters sequence or NL-terminator
  536. // References:
  537. // "7.4.1.2 Encoding Syntax", [1]
  538. // "7.5 <PROGRAM MESSAGE TERMINATOR>", [1]
  539. // Parameters:
  540. // @xObj - parser context, must be prepared by @prepareParserContext
  541. // ... before each call. If it is needed to continue the processing, the
  542. // ... @bKeepContext parameter duing the call @prepareParserContext must
  543. // ... be set to 'true', and otherwise, to restart parsing the parameter
  544. // ... must be set to 'false'.
  545. // Returns:
  546. // eScpiParserStatus_failed - error, can not parse data;
  547. // eScpiParserStatus_success - success, the string has been successfully parsed;
  548. // eScpiParserStatus_need_data - warning, the string can not be parsed due to
  549. // there no enough data to process.
  550. eScpiParserStatus_t parseWhiteSequence( xParseEntry_t * xObj );
  551. // =================================================================================================================
  552. // @checkNotEndOfString
  553. // "Parser-function", checks if the parser context not reached the end of string
  554. // Parameters:
  555. // @xObj - parser context, must be prepared by @prepareParserContext
  556. // ... before each call. If it is needed to continue the processing, the
  557. // ... @bKeepContext parameter duing the call @prepareParserContext must
  558. // ... be set to 'true', and otherwise, to restart parsing the parameter
  559. // ... must be set to 'false'.
  560. // Returns:
  561. // eScpiParserStatus_failed - error, end-of-string is reached
  562. // eScpiParserStatus_success - success, end-of-string is not reached
  563. // eScpiParserStatus_invalid - error, invalid parameters
  564. eScpiParserStatus_t checkNotEndOfString( xParseEntry_t * xObj );
  565. // ==============================================================================================
  566. // @parseArguments
  567. // Common parser function to analyze and recognize command arguments using the
  568. // template preassigned by @DECLARE_SCPI_ARGS macro.
  569. // Parameters:
  570. // @xObj - parser context, must be prepared by @prepareParserContext
  571. // ... before each call. If it is needed to continue the processing, the
  572. // ... @bKeepContext parameter duing the call @prepareParserContext must
  573. // ... be set to 'true', and otherwise, to restart parsing the parameter
  574. // ... must be set to 'false'.
  575. // @argTokens - array of argument string tokens to store parameters iterators;
  576. // @argTypes - array of argument types [eScpiArgType_t] to set the parameters parsing methods;
  577. // @entityTypes - array of entity types [eScpiEntityType_t] to be written after successful call; optional;
  578. // @argN - number of arguments (including optional and mandatory ones);
  579. // @argOptionalN - number of optional only arguments;
  580. // @pArgParsed - pointer to the variable to store the number of successfully
  581. // ... parsed arguments, valid only if eScpiParserStatus_success status is returned,
  582. // ... Otherwise, if the status is eScpiParserStatus_failed this value indicates
  583. // ... the index of erroneous parameter. Can not be NULL.
  584. // Returns:
  585. // eScpiParserStatus_failed - error, can not parse data;
  586. // eScpiParserStatus_invalid - error, invalid parameters;
  587. // eScpiParserStatus_success - success, the string has been successfully parsed;
  588. // eScpiParserStatus_need_data - warning, the string can not be parsed due to
  589. // there no enough data to process.
  590. eScpiParserStatus_t parseArguments( xParseEntry_t * xObj,
  591. sStrToken_t * argTokens,
  592. const uint8_t * argTypes,
  593. uint8_t * entityTypes,
  594. size_t argN,
  595. size_t argOptionalN,
  596. uint8_t * pArgParsed );
  597. eScpiParserStatus_t parseArrayArguments( xParseEntry_t * xObj,
  598. uint8_t * argTokens,
  599. size_t * argNumber,
  600. const uint8_t * argTypes,
  601. uint8_t * entityTypes,
  602. size_t argN,
  603. size_t argOptionalN,
  604. uint8_t * pArgParsed );
  605. #endif