https://github.com/j123b567/scpi-parser
Dependents: scpi_sx127x scpi_sx127x_firstTest MLX90418_I2C_master
src/parser.c@1:b497f235115a, 2015-08-07 (annotated)
- Committer:
- dudmuck
- Date:
- Fri Aug 07 21:54:11 2015 +0000
- Revision:
- 1:b497f235115a
- Parent:
- 0:aad43948c45c
update from github commit 6e5e3e0e3fc450eaf53feee059824ad85c4f270d
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
dudmuck | 0:aad43948c45c | 1 | /*- |
dudmuck | 0:aad43948c45c | 2 | * Copyright (c) 2012-2013 Jan Breuer, |
dudmuck | 0:aad43948c45c | 3 | * |
dudmuck | 0:aad43948c45c | 4 | * All Rights Reserved |
dudmuck | 1:b497f235115a | 5 | * |
dudmuck | 0:aad43948c45c | 6 | * Redistribution and use in source and binary forms, with or without |
dudmuck | 0:aad43948c45c | 7 | * modification, are permitted provided that the following conditions are |
dudmuck | 0:aad43948c45c | 8 | * met: |
dudmuck | 0:aad43948c45c | 9 | * 1. Redistributions of source code must retain the above copyright notice, |
dudmuck | 0:aad43948c45c | 10 | * this list of conditions and the following disclaimer. |
dudmuck | 0:aad43948c45c | 11 | * 2. Redistributions in binary form must reproduce the above copyright |
dudmuck | 0:aad43948c45c | 12 | * notice, this list of conditions and the following disclaimer in the |
dudmuck | 0:aad43948c45c | 13 | * documentation and/or other materials provided with the distribution. |
dudmuck | 1:b497f235115a | 14 | * |
dudmuck | 0:aad43948c45c | 15 | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR |
dudmuck | 0:aad43948c45c | 16 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
dudmuck | 0:aad43948c45c | 17 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
dudmuck | 0:aad43948c45c | 18 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE |
dudmuck | 0:aad43948c45c | 19 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
dudmuck | 0:aad43948c45c | 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
dudmuck | 0:aad43948c45c | 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
dudmuck | 0:aad43948c45c | 22 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
dudmuck | 0:aad43948c45c | 23 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
dudmuck | 0:aad43948c45c | 24 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
dudmuck | 0:aad43948c45c | 25 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
dudmuck | 0:aad43948c45c | 26 | */ |
dudmuck | 0:aad43948c45c | 27 | |
dudmuck | 0:aad43948c45c | 28 | /** |
dudmuck | 0:aad43948c45c | 29 | * @file scpi_parser.c |
dudmuck | 0:aad43948c45c | 30 | * @date Thu Nov 15 10:58:45 UTC 2012 |
dudmuck | 1:b497f235115a | 31 | * |
dudmuck | 0:aad43948c45c | 32 | * @brief SCPI parser implementation |
dudmuck | 1:b497f235115a | 33 | * |
dudmuck | 1:b497f235115a | 34 | * |
dudmuck | 0:aad43948c45c | 35 | */ |
dudmuck | 0:aad43948c45c | 36 | |
dudmuck | 0:aad43948c45c | 37 | #include <ctype.h> |
dudmuck | 0:aad43948c45c | 38 | #include <string.h> |
dudmuck | 0:aad43948c45c | 39 | |
dudmuck | 0:aad43948c45c | 40 | #include "scpi/config.h" |
dudmuck | 0:aad43948c45c | 41 | #include "scpi/parser.h" |
dudmuck | 1:b497f235115a | 42 | #include "parser_private.h" |
dudmuck | 1:b497f235115a | 43 | #include "lexer_private.h" |
dudmuck | 0:aad43948c45c | 44 | #include "scpi/error.h" |
dudmuck | 0:aad43948c45c | 45 | #include "scpi/constants.h" |
dudmuck | 1:b497f235115a | 46 | #include "scpi/utils.h" |
dudmuck | 0:aad43948c45c | 47 | |
dudmuck | 0:aad43948c45c | 48 | /** |
dudmuck | 0:aad43948c45c | 49 | * Write data to SCPI output |
dudmuck | 0:aad43948c45c | 50 | * @param context |
dudmuck | 0:aad43948c45c | 51 | * @param data |
dudmuck | 0:aad43948c45c | 52 | * @param len - lenght of data to be written |
dudmuck | 0:aad43948c45c | 53 | * @return number of bytes written |
dudmuck | 0:aad43948c45c | 54 | */ |
dudmuck | 0:aad43948c45c | 55 | static size_t writeData(scpi_t * context, const char * data, size_t len) { |
dudmuck | 0:aad43948c45c | 56 | return context->interface->write(context, data, len); |
dudmuck | 0:aad43948c45c | 57 | } |
dudmuck | 0:aad43948c45c | 58 | |
dudmuck | 0:aad43948c45c | 59 | /** |
dudmuck | 0:aad43948c45c | 60 | * Flush data to SCPI output |
dudmuck | 0:aad43948c45c | 61 | * @param context |
dudmuck | 0:aad43948c45c | 62 | * @return |
dudmuck | 0:aad43948c45c | 63 | */ |
dudmuck | 0:aad43948c45c | 64 | static int flushData(scpi_t * context) { |
dudmuck | 0:aad43948c45c | 65 | if (context && context->interface && context->interface->flush) { |
dudmuck | 0:aad43948c45c | 66 | return context->interface->flush(context); |
dudmuck | 0:aad43948c45c | 67 | } else { |
dudmuck | 0:aad43948c45c | 68 | return SCPI_RES_OK; |
dudmuck | 0:aad43948c45c | 69 | } |
dudmuck | 0:aad43948c45c | 70 | } |
dudmuck | 0:aad43948c45c | 71 | |
dudmuck | 0:aad43948c45c | 72 | /** |
dudmuck | 0:aad43948c45c | 73 | * Write result delimiter to output |
dudmuck | 0:aad43948c45c | 74 | * @param context |
dudmuck | 0:aad43948c45c | 75 | * @return number of bytes written |
dudmuck | 0:aad43948c45c | 76 | */ |
dudmuck | 0:aad43948c45c | 77 | static size_t writeDelimiter(scpi_t * context) { |
dudmuck | 0:aad43948c45c | 78 | if (context->output_count > 0) { |
dudmuck | 1:b497f235115a | 79 | return writeData(context, ",", 1); |
dudmuck | 0:aad43948c45c | 80 | } else { |
dudmuck | 0:aad43948c45c | 81 | return 0; |
dudmuck | 0:aad43948c45c | 82 | } |
dudmuck | 0:aad43948c45c | 83 | } |
dudmuck | 0:aad43948c45c | 84 | |
dudmuck | 0:aad43948c45c | 85 | /** |
dudmuck | 0:aad43948c45c | 86 | * Conditionaly write "New Line" |
dudmuck | 0:aad43948c45c | 87 | * @param context |
dudmuck | 0:aad43948c45c | 88 | * @return number of characters written |
dudmuck | 0:aad43948c45c | 89 | */ |
dudmuck | 0:aad43948c45c | 90 | static size_t writeNewLine(scpi_t * context) { |
dudmuck | 0:aad43948c45c | 91 | if (context->output_count > 0) { |
dudmuck | 0:aad43948c45c | 92 | size_t len; |
dudmuck | 1:b497f235115a | 93 | #ifndef SCPI_LINE_ENDING |
dudmuck | 1:b497f235115a | 94 | #error no termination character defined |
dudmuck | 1:b497f235115a | 95 | #endif |
dudmuck | 1:b497f235115a | 96 | len = writeData(context, SCPI_LINE_ENDING, strlen(SCPI_LINE_ENDING)); |
dudmuck | 0:aad43948c45c | 97 | flushData(context); |
dudmuck | 0:aad43948c45c | 98 | return len; |
dudmuck | 0:aad43948c45c | 99 | } else { |
dudmuck | 0:aad43948c45c | 100 | return 0; |
dudmuck | 0:aad43948c45c | 101 | } |
dudmuck | 0:aad43948c45c | 102 | } |
dudmuck | 0:aad43948c45c | 103 | |
dudmuck | 0:aad43948c45c | 104 | /** |
dudmuck | 1:b497f235115a | 105 | * Conditionaly write ";" |
dudmuck | 1:b497f235115a | 106 | * @param context |
dudmuck | 1:b497f235115a | 107 | * @return number of characters written |
dudmuck | 1:b497f235115a | 108 | */ |
dudmuck | 1:b497f235115a | 109 | static size_t writeSemicolon(scpi_t * context) { |
dudmuck | 1:b497f235115a | 110 | if (context->output_count > 0) { |
dudmuck | 1:b497f235115a | 111 | return writeData(context, ";", 1); |
dudmuck | 1:b497f235115a | 112 | } else { |
dudmuck | 1:b497f235115a | 113 | return 0; |
dudmuck | 1:b497f235115a | 114 | } |
dudmuck | 1:b497f235115a | 115 | } |
dudmuck | 1:b497f235115a | 116 | |
dudmuck | 1:b497f235115a | 117 | /** |
dudmuck | 0:aad43948c45c | 118 | * Process command |
dudmuck | 0:aad43948c45c | 119 | * @param context |
dudmuck | 0:aad43948c45c | 120 | */ |
dudmuck | 0:aad43948c45c | 121 | static void processCommand(scpi_t * context) { |
dudmuck | 1:b497f235115a | 122 | const scpi_command_t * cmd = context->param_list.cmd; |
dudmuck | 1:b497f235115a | 123 | lex_state_t * state = &context->param_list.lex_state; |
dudmuck | 1:b497f235115a | 124 | |
dudmuck | 1:b497f235115a | 125 | /* conditionaly write ; */ |
dudmuck | 1:b497f235115a | 126 | writeSemicolon(context); |
dudmuck | 0:aad43948c45c | 127 | |
dudmuck | 0:aad43948c45c | 128 | context->cmd_error = FALSE; |
dudmuck | 0:aad43948c45c | 129 | context->output_count = 0; |
dudmuck | 0:aad43948c45c | 130 | context->input_count = 0; |
dudmuck | 0:aad43948c45c | 131 | |
dudmuck | 0:aad43948c45c | 132 | /* if callback exists - call command callback */ |
dudmuck | 0:aad43948c45c | 133 | if (cmd->callback != NULL) { |
dudmuck | 0:aad43948c45c | 134 | if ((cmd->callback(context) != SCPI_RES_OK) && !context->cmd_error) { |
dudmuck | 0:aad43948c45c | 135 | SCPI_ErrorPush(context, SCPI_ERROR_EXECUTION_ERROR); |
dudmuck | 0:aad43948c45c | 136 | } |
dudmuck | 0:aad43948c45c | 137 | } |
dudmuck | 0:aad43948c45c | 138 | |
dudmuck | 0:aad43948c45c | 139 | /* set error if command callback did not read all parameters */ |
dudmuck | 1:b497f235115a | 140 | if (state->pos < (state->buffer + state->len) && !context->cmd_error) { |
dudmuck | 0:aad43948c45c | 141 | SCPI_ErrorPush(context, SCPI_ERROR_PARAMETER_NOT_ALLOWED); |
dudmuck | 0:aad43948c45c | 142 | } |
dudmuck | 0:aad43948c45c | 143 | } |
dudmuck | 0:aad43948c45c | 144 | |
dudmuck | 0:aad43948c45c | 145 | /** |
dudmuck | 0:aad43948c45c | 146 | * Cycle all patterns and search matching pattern. Execute command callback. |
dudmuck | 0:aad43948c45c | 147 | * @param context |
dudmuck | 0:aad43948c45c | 148 | * @result TRUE if context->paramlist is filled with correct values |
dudmuck | 0:aad43948c45c | 149 | */ |
dudmuck | 1:b497f235115a | 150 | static scpi_bool_t findCommandHeader(scpi_t * context, const char * header, int len) { |
dudmuck | 0:aad43948c45c | 151 | int32_t i; |
dudmuck | 0:aad43948c45c | 152 | const scpi_command_t * cmd; |
dudmuck | 0:aad43948c45c | 153 | |
dudmuck | 0:aad43948c45c | 154 | for (i = 0; context->cmdlist[i].pattern != NULL; i++) { |
dudmuck | 0:aad43948c45c | 155 | cmd = &context->cmdlist[i]; |
dudmuck | 1:b497f235115a | 156 | if (matchCommand(cmd->pattern, header, len, NULL, 0)) { |
dudmuck | 1:b497f235115a | 157 | context->param_list.cmd = cmd; |
dudmuck | 0:aad43948c45c | 158 | return TRUE; |
dudmuck | 0:aad43948c45c | 159 | } |
dudmuck | 0:aad43948c45c | 160 | } |
dudmuck | 0:aad43948c45c | 161 | return FALSE; |
dudmuck | 0:aad43948c45c | 162 | } |
dudmuck | 0:aad43948c45c | 163 | |
dudmuck | 0:aad43948c45c | 164 | /** |
dudmuck | 0:aad43948c45c | 165 | * Parse one command line |
dudmuck | 0:aad43948c45c | 166 | * @param context |
dudmuck | 0:aad43948c45c | 167 | * @param data - complete command line |
dudmuck | 0:aad43948c45c | 168 | * @param len - command line length |
dudmuck | 0:aad43948c45c | 169 | * @return 1 if the last evaluated command was found |
dudmuck | 0:aad43948c45c | 170 | */ |
dudmuck | 1:b497f235115a | 171 | int SCPI_Parse(scpi_t * context, char * data, int len) { |
dudmuck | 0:aad43948c45c | 172 | int result = 0; |
dudmuck | 1:b497f235115a | 173 | scpi_parser_state_t * state; |
dudmuck | 1:b497f235115a | 174 | int r; |
dudmuck | 1:b497f235115a | 175 | scpi_token_t cmd_prev = {SCPI_TOKEN_UNKNOWN, NULL, 0}; |
dudmuck | 0:aad43948c45c | 176 | |
dudmuck | 0:aad43948c45c | 177 | if (context == NULL) { |
dudmuck | 0:aad43948c45c | 178 | return -1; |
dudmuck | 0:aad43948c45c | 179 | } |
dudmuck | 0:aad43948c45c | 180 | |
dudmuck | 1:b497f235115a | 181 | state = &context->parser_state; |
dudmuck | 1:b497f235115a | 182 | context->output_count = 0; |
dudmuck | 1:b497f235115a | 183 | |
dudmuck | 1:b497f235115a | 184 | while (1) { |
dudmuck | 0:aad43948c45c | 185 | result = 0; |
dudmuck | 1:b497f235115a | 186 | |
dudmuck | 1:b497f235115a | 187 | r = scpiParser_detectProgramMessageUnit(state, data, len); |
dudmuck | 1:b497f235115a | 188 | |
dudmuck | 1:b497f235115a | 189 | if (state->programHeader.type == SCPI_TOKEN_INVALID) { |
dudmuck | 1:b497f235115a | 190 | SCPI_ErrorPush(context, SCPI_ERROR_INVALID_CHARACTER); |
dudmuck | 1:b497f235115a | 191 | } else if (state->programHeader.len > 0) { |
dudmuck | 1:b497f235115a | 192 | |
dudmuck | 1:b497f235115a | 193 | composeCompoundCommand(&cmd_prev, &state->programHeader); |
dudmuck | 1:b497f235115a | 194 | |
dudmuck | 1:b497f235115a | 195 | if (findCommandHeader(context, state->programHeader.ptr, state->programHeader.len)) { |
dudmuck | 1:b497f235115a | 196 | |
dudmuck | 1:b497f235115a | 197 | context->param_list.lex_state.buffer = state->programData.ptr; |
dudmuck | 1:b497f235115a | 198 | context->param_list.lex_state.pos = context->param_list.lex_state.buffer; |
dudmuck | 1:b497f235115a | 199 | context->param_list.lex_state.len = state->programData.len; |
dudmuck | 1:b497f235115a | 200 | context->param_list.cmd_raw.data = state->programHeader.ptr; |
dudmuck | 1:b497f235115a | 201 | context->param_list.cmd_raw.position = 0; |
dudmuck | 1:b497f235115a | 202 | context->param_list.cmd_raw.length = state->programHeader.len; |
dudmuck | 1:b497f235115a | 203 | |
dudmuck | 0:aad43948c45c | 204 | processCommand(context); |
dudmuck | 1:b497f235115a | 205 | |
dudmuck | 0:aad43948c45c | 206 | result = 1; |
dudmuck | 1:b497f235115a | 207 | cmd_prev = state->programHeader; |
dudmuck | 0:aad43948c45c | 208 | } else { |
dudmuck | 0:aad43948c45c | 209 | SCPI_ErrorPush(context, SCPI_ERROR_UNDEFINED_HEADER); |
dudmuck | 0:aad43948c45c | 210 | } |
dudmuck | 0:aad43948c45c | 211 | } |
dudmuck | 1:b497f235115a | 212 | |
dudmuck | 1:b497f235115a | 213 | if (r < len) { |
dudmuck | 1:b497f235115a | 214 | data += r; |
dudmuck | 1:b497f235115a | 215 | len -= r; |
dudmuck | 1:b497f235115a | 216 | } else { |
dudmuck | 1:b497f235115a | 217 | break; |
dudmuck | 1:b497f235115a | 218 | } |
dudmuck | 1:b497f235115a | 219 | |
dudmuck | 0:aad43948c45c | 220 | } |
dudmuck | 1:b497f235115a | 221 | |
dudmuck | 1:b497f235115a | 222 | /* conditionaly write new line */ |
dudmuck | 1:b497f235115a | 223 | writeNewLine(context); |
dudmuck | 1:b497f235115a | 224 | |
dudmuck | 0:aad43948c45c | 225 | return result; |
dudmuck | 0:aad43948c45c | 226 | } |
dudmuck | 0:aad43948c45c | 227 | |
dudmuck | 0:aad43948c45c | 228 | /** |
dudmuck | 0:aad43948c45c | 229 | * Initialize SCPI context structure |
dudmuck | 0:aad43948c45c | 230 | * @param context |
dudmuck | 0:aad43948c45c | 231 | * @param command_list |
dudmuck | 0:aad43948c45c | 232 | * @param buffer |
dudmuck | 0:aad43948c45c | 233 | * @param interface |
dudmuck | 0:aad43948c45c | 234 | */ |
dudmuck | 0:aad43948c45c | 235 | void SCPI_Init(scpi_t * context) { |
dudmuck | 0:aad43948c45c | 236 | if (context->idn[0] == NULL) { |
dudmuck | 0:aad43948c45c | 237 | context->idn[0] = SCPI_DEFAULT_1_MANUFACTURE; |
dudmuck | 0:aad43948c45c | 238 | } |
dudmuck | 0:aad43948c45c | 239 | if (context->idn[1] == NULL) { |
dudmuck | 0:aad43948c45c | 240 | context->idn[1] = SCPI_DEFAULT_2_MODEL; |
dudmuck | 0:aad43948c45c | 241 | } |
dudmuck | 0:aad43948c45c | 242 | if (context->idn[2] == NULL) { |
dudmuck | 0:aad43948c45c | 243 | context->idn[2] = SCPI_DEFAULT_3; |
dudmuck | 0:aad43948c45c | 244 | } |
dudmuck | 0:aad43948c45c | 245 | if (context->idn[3] == NULL) { |
dudmuck | 0:aad43948c45c | 246 | context->idn[3] = SCPI_DEFAULT_4_REVISION; |
dudmuck | 0:aad43948c45c | 247 | } |
dudmuck | 1:b497f235115a | 248 | |
dudmuck | 0:aad43948c45c | 249 | context->buffer.position = 0; |
dudmuck | 0:aad43948c45c | 250 | SCPI_ErrorInit(context); |
dudmuck | 0:aad43948c45c | 251 | } |
dudmuck | 0:aad43948c45c | 252 | |
dudmuck | 0:aad43948c45c | 253 | /** |
dudmuck | 0:aad43948c45c | 254 | * Interface to the application. Adds data to system buffer and try to search |
dudmuck | 0:aad43948c45c | 255 | * command line termination. If the termination is found or if len=0, command |
dudmuck | 0:aad43948c45c | 256 | * parser is called. |
dudmuck | 1:b497f235115a | 257 | * |
dudmuck | 0:aad43948c45c | 258 | * @param context |
dudmuck | 0:aad43948c45c | 259 | * @param data - data to process |
dudmuck | 0:aad43948c45c | 260 | * @param len - length of data |
dudmuck | 1:b497f235115a | 261 | * @return |
dudmuck | 0:aad43948c45c | 262 | */ |
dudmuck | 1:b497f235115a | 263 | int SCPI_Input(scpi_t * context, const char * data, int len) { |
dudmuck | 0:aad43948c45c | 264 | int result = 0; |
dudmuck | 1:b497f235115a | 265 | size_t totcmdlen = 0; |
dudmuck | 1:b497f235115a | 266 | int cmdlen = 0; |
dudmuck | 1:b497f235115a | 267 | |
dudmuck | 0:aad43948c45c | 268 | if (len == 0) { |
dudmuck | 0:aad43948c45c | 269 | context->buffer.data[context->buffer.position] = 0; |
dudmuck | 0:aad43948c45c | 270 | result = SCPI_Parse(context, context->buffer.data, context->buffer.position); |
dudmuck | 0:aad43948c45c | 271 | context->buffer.position = 0; |
dudmuck | 0:aad43948c45c | 272 | } else { |
dudmuck | 1:b497f235115a | 273 | int buffer_free; |
dudmuck | 1:b497f235115a | 274 | |
dudmuck | 0:aad43948c45c | 275 | buffer_free = context->buffer.length - context->buffer.position; |
dudmuck | 0:aad43948c45c | 276 | if (len > (buffer_free - 1)) { |
dudmuck | 0:aad43948c45c | 277 | return -1; |
dudmuck | 0:aad43948c45c | 278 | } |
dudmuck | 0:aad43948c45c | 279 | memcpy(&context->buffer.data[context->buffer.position], data, len); |
dudmuck | 0:aad43948c45c | 280 | context->buffer.position += len; |
dudmuck | 0:aad43948c45c | 281 | context->buffer.data[context->buffer.position] = 0; |
dudmuck | 0:aad43948c45c | 282 | |
dudmuck | 1:b497f235115a | 283 | |
dudmuck | 1:b497f235115a | 284 | while (1) { |
dudmuck | 1:b497f235115a | 285 | cmdlen = scpiParser_detectProgramMessageUnit(&context->parser_state, context->buffer.data + totcmdlen, context->buffer.position - totcmdlen); |
dudmuck | 1:b497f235115a | 286 | totcmdlen += cmdlen; |
dudmuck | 1:b497f235115a | 287 | |
dudmuck | 1:b497f235115a | 288 | if (context->parser_state.termination == SCPI_MESSAGE_TERMINATION_NL) { |
dudmuck | 1:b497f235115a | 289 | result = SCPI_Parse(context, context->buffer.data, totcmdlen); |
dudmuck | 1:b497f235115a | 290 | memmove(context->buffer.data, context->buffer.data + totcmdlen, context->buffer.position - totcmdlen); |
dudmuck | 1:b497f235115a | 291 | context->buffer.position -= totcmdlen; |
dudmuck | 1:b497f235115a | 292 | totcmdlen = 0; |
dudmuck | 1:b497f235115a | 293 | } else { |
dudmuck | 1:b497f235115a | 294 | if (context->parser_state.programHeader.type == SCPI_TOKEN_UNKNOWN) break; |
dudmuck | 1:b497f235115a | 295 | if (totcmdlen >= context->buffer.position) break; |
dudmuck | 1:b497f235115a | 296 | } |
dudmuck | 0:aad43948c45c | 297 | } |
dudmuck | 0:aad43948c45c | 298 | } |
dudmuck | 0:aad43948c45c | 299 | |
dudmuck | 0:aad43948c45c | 300 | return result; |
dudmuck | 0:aad43948c45c | 301 | } |
dudmuck | 0:aad43948c45c | 302 | |
dudmuck | 0:aad43948c45c | 303 | /* writing results */ |
dudmuck | 0:aad43948c45c | 304 | |
dudmuck | 0:aad43948c45c | 305 | /** |
dudmuck | 0:aad43948c45c | 306 | * Write raw string result to the output |
dudmuck | 0:aad43948c45c | 307 | * @param context |
dudmuck | 0:aad43948c45c | 308 | * @param data |
dudmuck | 1:b497f235115a | 309 | * @return |
dudmuck | 0:aad43948c45c | 310 | */ |
dudmuck | 1:b497f235115a | 311 | size_t SCPI_ResultCharacters(scpi_t * context, const char * data, size_t len) { |
dudmuck | 0:aad43948c45c | 312 | size_t result = 0; |
dudmuck | 0:aad43948c45c | 313 | result += writeDelimiter(context); |
dudmuck | 0:aad43948c45c | 314 | result += writeData(context, data, len); |
dudmuck | 0:aad43948c45c | 315 | context->output_count++; |
dudmuck | 0:aad43948c45c | 316 | return result; |
dudmuck | 0:aad43948c45c | 317 | } |
dudmuck | 0:aad43948c45c | 318 | |
dudmuck | 0:aad43948c45c | 319 | /** |
dudmuck | 0:aad43948c45c | 320 | * Write integer value to the result |
dudmuck | 0:aad43948c45c | 321 | * @param context |
dudmuck | 0:aad43948c45c | 322 | * @param val |
dudmuck | 1:b497f235115a | 323 | * @return |
dudmuck | 0:aad43948c45c | 324 | */ |
dudmuck | 0:aad43948c45c | 325 | size_t SCPI_ResultInt(scpi_t * context, int32_t val) { |
dudmuck | 1:b497f235115a | 326 | return SCPI_ResultIntBase(context, val, 10); |
dudmuck | 1:b497f235115a | 327 | } |
dudmuck | 1:b497f235115a | 328 | |
dudmuck | 1:b497f235115a | 329 | /** |
dudmuck | 1:b497f235115a | 330 | * Return prefix of nondecimal base |
dudmuck | 1:b497f235115a | 331 | * @param base |
dudmuck | 1:b497f235115a | 332 | * @return |
dudmuck | 1:b497f235115a | 333 | */ |
dudmuck | 1:b497f235115a | 334 | static const char * getBasePrefix(int8_t base) { |
dudmuck | 1:b497f235115a | 335 | switch (base) { |
dudmuck | 1:b497f235115a | 336 | case 2: return "#B"; |
dudmuck | 1:b497f235115a | 337 | case 8: return "#Q"; |
dudmuck | 1:b497f235115a | 338 | case 16: return "#H"; |
dudmuck | 1:b497f235115a | 339 | default: return NULL; |
dudmuck | 1:b497f235115a | 340 | } |
dudmuck | 1:b497f235115a | 341 | } |
dudmuck | 1:b497f235115a | 342 | |
dudmuck | 1:b497f235115a | 343 | /** |
dudmuck | 1:b497f235115a | 344 | * Write integer value in specific base to the result |
dudmuck | 1:b497f235115a | 345 | * @param context |
dudmuck | 1:b497f235115a | 346 | * @param val |
dudmuck | 1:b497f235115a | 347 | * @param base |
dudmuck | 1:b497f235115a | 348 | * @return |
dudmuck | 1:b497f235115a | 349 | */ |
dudmuck | 1:b497f235115a | 350 | size_t SCPI_ResultIntBase(scpi_t * context, int32_t val, int8_t base) { |
dudmuck | 1:b497f235115a | 351 | char buffer[33]; |
dudmuck | 1:b497f235115a | 352 | const char * basePrefix; |
dudmuck | 0:aad43948c45c | 353 | size_t result = 0; |
dudmuck | 1:b497f235115a | 354 | size_t len; |
dudmuck | 1:b497f235115a | 355 | |
dudmuck | 1:b497f235115a | 356 | len = SCPI_LongToStr(val, buffer, sizeof (buffer), base); |
dudmuck | 1:b497f235115a | 357 | basePrefix = getBasePrefix(base); |
dudmuck | 1:b497f235115a | 358 | |
dudmuck | 0:aad43948c45c | 359 | result += writeDelimiter(context); |
dudmuck | 1:b497f235115a | 360 | if (basePrefix != NULL) { |
dudmuck | 1:b497f235115a | 361 | result += writeData(context, basePrefix, 2); |
dudmuck | 1:b497f235115a | 362 | } |
dudmuck | 0:aad43948c45c | 363 | result += writeData(context, buffer, len); |
dudmuck | 0:aad43948c45c | 364 | context->output_count++; |
dudmuck | 0:aad43948c45c | 365 | return result; |
dudmuck | 0:aad43948c45c | 366 | } |
dudmuck | 0:aad43948c45c | 367 | |
dudmuck | 0:aad43948c45c | 368 | /** |
dudmuck | 0:aad43948c45c | 369 | * Write double walue to the result |
dudmuck | 0:aad43948c45c | 370 | * @param context |
dudmuck | 0:aad43948c45c | 371 | * @param val |
dudmuck | 1:b497f235115a | 372 | * @return |
dudmuck | 0:aad43948c45c | 373 | */ |
dudmuck | 0:aad43948c45c | 374 | size_t SCPI_ResultDouble(scpi_t * context, double val) { |
dudmuck | 0:aad43948c45c | 375 | char buffer[32]; |
dudmuck | 0:aad43948c45c | 376 | size_t result = 0; |
dudmuck | 1:b497f235115a | 377 | size_t len = SCPI_DoubleToStr(val, buffer, sizeof (buffer)); |
dudmuck | 0:aad43948c45c | 378 | result += writeDelimiter(context); |
dudmuck | 0:aad43948c45c | 379 | result += writeData(context, buffer, len); |
dudmuck | 0:aad43948c45c | 380 | context->output_count++; |
dudmuck | 0:aad43948c45c | 381 | return result; |
dudmuck | 0:aad43948c45c | 382 | |
dudmuck | 0:aad43948c45c | 383 | } |
dudmuck | 0:aad43948c45c | 384 | |
dudmuck | 0:aad43948c45c | 385 | /** |
dudmuck | 0:aad43948c45c | 386 | * Write string withn " to the result |
dudmuck | 0:aad43948c45c | 387 | * @param context |
dudmuck | 0:aad43948c45c | 388 | * @param data |
dudmuck | 1:b497f235115a | 389 | * @return |
dudmuck | 0:aad43948c45c | 390 | */ |
dudmuck | 0:aad43948c45c | 391 | size_t SCPI_ResultText(scpi_t * context, const char * data) { |
dudmuck | 0:aad43948c45c | 392 | size_t result = 0; |
dudmuck | 0:aad43948c45c | 393 | result += writeDelimiter(context); |
dudmuck | 0:aad43948c45c | 394 | result += writeData(context, "\"", 1); |
dudmuck | 1:b497f235115a | 395 | // TODO: convert " to "" |
dudmuck | 0:aad43948c45c | 396 | result += writeData(context, data, strlen(data)); |
dudmuck | 0:aad43948c45c | 397 | result += writeData(context, "\"", 1); |
dudmuck | 0:aad43948c45c | 398 | context->output_count++; |
dudmuck | 0:aad43948c45c | 399 | return result; |
dudmuck | 0:aad43948c45c | 400 | } |
dudmuck | 0:aad43948c45c | 401 | |
dudmuck | 0:aad43948c45c | 402 | /** |
dudmuck | 1:b497f235115a | 403 | * Write arbitrary block program data to the result |
dudmuck | 0:aad43948c45c | 404 | * @param context |
dudmuck | 1:b497f235115a | 405 | * @param data |
dudmuck | 1:b497f235115a | 406 | * @param len |
dudmuck | 1:b497f235115a | 407 | * @return |
dudmuck | 0:aad43948c45c | 408 | */ |
dudmuck | 1:b497f235115a | 409 | size_t SCPI_ResultArbitraryBlock(scpi_t * context, const char * data, size_t len) { |
dudmuck | 1:b497f235115a | 410 | size_t result = 0; |
dudmuck | 1:b497f235115a | 411 | char block_header[12]; |
dudmuck | 1:b497f235115a | 412 | size_t header_len; |
dudmuck | 1:b497f235115a | 413 | block_header[0] = '#'; |
dudmuck | 1:b497f235115a | 414 | SCPI_LongToStr(len, block_header + 2, 10, 10); |
dudmuck | 1:b497f235115a | 415 | |
dudmuck | 1:b497f235115a | 416 | header_len = strlen(block_header + 2); |
dudmuck | 1:b497f235115a | 417 | block_header[1] = (char)(header_len + '0'); |
dudmuck | 1:b497f235115a | 418 | |
dudmuck | 1:b497f235115a | 419 | result += writeData(context, block_header, header_len + 2); |
dudmuck | 1:b497f235115a | 420 | result += writeData(context, data, len); |
dudmuck | 1:b497f235115a | 421 | |
dudmuck | 1:b497f235115a | 422 | context->output_count++; |
dudmuck | 1:b497f235115a | 423 | return result; |
dudmuck | 0:aad43948c45c | 424 | } |
dudmuck | 0:aad43948c45c | 425 | |
dudmuck | 0:aad43948c45c | 426 | /** |
dudmuck | 1:b497f235115a | 427 | * Write boolean value to the result |
dudmuck | 0:aad43948c45c | 428 | * @param context |
dudmuck | 1:b497f235115a | 429 | * @param val |
dudmuck | 1:b497f235115a | 430 | * @return |
dudmuck | 0:aad43948c45c | 431 | */ |
dudmuck | 1:b497f235115a | 432 | size_t SCPI_ResultBool(scpi_t * context, scpi_bool_t val) { |
dudmuck | 1:b497f235115a | 433 | return SCPI_ResultIntBase(context, val ? 1 : 0, 10); |
dudmuck | 1:b497f235115a | 434 | } |
dudmuck | 1:b497f235115a | 435 | |
dudmuck | 1:b497f235115a | 436 | /* parsing parameters */ |
dudmuck | 1:b497f235115a | 437 | |
dudmuck | 1:b497f235115a | 438 | /** |
dudmuck | 1:b497f235115a | 439 | * Invalidate token |
dudmuck | 1:b497f235115a | 440 | * @param token |
dudmuck | 1:b497f235115a | 441 | * @param ptr |
dudmuck | 1:b497f235115a | 442 | */ |
dudmuck | 1:b497f235115a | 443 | static void invalidateToken(scpi_token_t * token, char * ptr) { |
dudmuck | 1:b497f235115a | 444 | token->len = 0; |
dudmuck | 1:b497f235115a | 445 | token->ptr = ptr; |
dudmuck | 1:b497f235115a | 446 | token->type = SCPI_TOKEN_UNKNOWN; |
dudmuck | 0:aad43948c45c | 447 | } |
dudmuck | 0:aad43948c45c | 448 | |
dudmuck | 0:aad43948c45c | 449 | /** |
dudmuck | 1:b497f235115a | 450 | * Get one parameter from command line |
dudmuck | 0:aad43948c45c | 451 | * @param context |
dudmuck | 1:b497f235115a | 452 | * @param parameter |
dudmuck | 0:aad43948c45c | 453 | * @param mandatory |
dudmuck | 1:b497f235115a | 454 | * @return |
dudmuck | 0:aad43948c45c | 455 | */ |
dudmuck | 1:b497f235115a | 456 | scpi_bool_t SCPI_Parameter(scpi_t * context, scpi_parameter_t * parameter, scpi_bool_t mandatory) { |
dudmuck | 1:b497f235115a | 457 | lex_state_t * state; |
dudmuck | 1:b497f235115a | 458 | |
dudmuck | 1:b497f235115a | 459 | if (!parameter) { |
dudmuck | 1:b497f235115a | 460 | SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); |
dudmuck | 1:b497f235115a | 461 | return FALSE; |
dudmuck | 1:b497f235115a | 462 | } |
dudmuck | 1:b497f235115a | 463 | |
dudmuck | 1:b497f235115a | 464 | invalidateToken(parameter, NULL); |
dudmuck | 1:b497f235115a | 465 | |
dudmuck | 1:b497f235115a | 466 | state = &context->param_list.lex_state; |
dudmuck | 1:b497f235115a | 467 | |
dudmuck | 1:b497f235115a | 468 | if (state->pos >= (state->buffer + state->len)) { |
dudmuck | 0:aad43948c45c | 469 | if (mandatory) { |
dudmuck | 0:aad43948c45c | 470 | SCPI_ErrorPush(context, SCPI_ERROR_MISSING_PARAMETER); |
dudmuck | 1:b497f235115a | 471 | } else { |
dudmuck | 1:b497f235115a | 472 | parameter->type = SCPI_TOKEN_PROGRAM_MNEMONIC; // TODO: select something different |
dudmuck | 0:aad43948c45c | 473 | } |
dudmuck | 0:aad43948c45c | 474 | return FALSE; |
dudmuck | 0:aad43948c45c | 475 | } |
dudmuck | 0:aad43948c45c | 476 | if (context->input_count != 0) { |
dudmuck | 1:b497f235115a | 477 | scpiLex_Comma(state, parameter); |
dudmuck | 1:b497f235115a | 478 | if (parameter->type != SCPI_TOKEN_COMMA) { |
dudmuck | 1:b497f235115a | 479 | invalidateToken(parameter, NULL); |
dudmuck | 0:aad43948c45c | 480 | SCPI_ErrorPush(context, SCPI_ERROR_INVALID_SEPARATOR); |
dudmuck | 0:aad43948c45c | 481 | return FALSE; |
dudmuck | 0:aad43948c45c | 482 | } |
dudmuck | 0:aad43948c45c | 483 | } |
dudmuck | 1:b497f235115a | 484 | |
dudmuck | 0:aad43948c45c | 485 | context->input_count++; |
dudmuck | 1:b497f235115a | 486 | |
dudmuck | 1:b497f235115a | 487 | scpiParser_parseProgramData(&context->param_list.lex_state, parameter); |
dudmuck | 1:b497f235115a | 488 | |
dudmuck | 1:b497f235115a | 489 | switch (parameter->type) { |
dudmuck | 1:b497f235115a | 490 | case SCPI_TOKEN_HEXNUM: |
dudmuck | 1:b497f235115a | 491 | case SCPI_TOKEN_OCTNUM: |
dudmuck | 1:b497f235115a | 492 | case SCPI_TOKEN_BINNUM: |
dudmuck | 1:b497f235115a | 493 | case SCPI_TOKEN_PROGRAM_MNEMONIC: |
dudmuck | 1:b497f235115a | 494 | case SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA: |
dudmuck | 1:b497f235115a | 495 | case SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA_WITH_SUFFIX: |
dudmuck | 1:b497f235115a | 496 | case SCPI_TOKEN_ARBITRARY_BLOCK_PROGRAM_DATA: |
dudmuck | 1:b497f235115a | 497 | case SCPI_TOKEN_SINGLE_QUOTE_PROGRAM_DATA: |
dudmuck | 1:b497f235115a | 498 | case SCPI_TOKEN_DOUBLE_QUOTE_PROGRAM_DATA: |
dudmuck | 1:b497f235115a | 499 | case SCPI_TOKEN_PROGRAM_EXPRESSION: |
dudmuck | 1:b497f235115a | 500 | return TRUE; |
dudmuck | 1:b497f235115a | 501 | default: |
dudmuck | 1:b497f235115a | 502 | invalidateToken(parameter, NULL); |
dudmuck | 1:b497f235115a | 503 | SCPI_ErrorPush(context, SCPI_ERROR_INVALID_STRING_DATA); |
dudmuck | 1:b497f235115a | 504 | return FALSE; |
dudmuck | 1:b497f235115a | 505 | } |
dudmuck | 1:b497f235115a | 506 | } |
dudmuck | 1:b497f235115a | 507 | |
dudmuck | 1:b497f235115a | 508 | /** |
dudmuck | 1:b497f235115a | 509 | * Detect if parameter is number |
dudmuck | 1:b497f235115a | 510 | * @param parameter |
dudmuck | 1:b497f235115a | 511 | * @param suffixAllowed |
dudmuck | 1:b497f235115a | 512 | * @return |
dudmuck | 1:b497f235115a | 513 | */ |
dudmuck | 1:b497f235115a | 514 | scpi_bool_t SCPI_ParamIsNumber(scpi_parameter_t * parameter, scpi_bool_t suffixAllowed) { |
dudmuck | 1:b497f235115a | 515 | switch (parameter->type) { |
dudmuck | 1:b497f235115a | 516 | case SCPI_TOKEN_HEXNUM: |
dudmuck | 1:b497f235115a | 517 | case SCPI_TOKEN_OCTNUM: |
dudmuck | 1:b497f235115a | 518 | case SCPI_TOKEN_BINNUM: |
dudmuck | 1:b497f235115a | 519 | case SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA: |
dudmuck | 1:b497f235115a | 520 | return TRUE; |
dudmuck | 1:b497f235115a | 521 | case SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA_WITH_SUFFIX: |
dudmuck | 1:b497f235115a | 522 | return suffixAllowed; |
dudmuck | 1:b497f235115a | 523 | default: |
dudmuck | 1:b497f235115a | 524 | return FALSE; |
dudmuck | 1:b497f235115a | 525 | } |
dudmuck | 0:aad43948c45c | 526 | } |
dudmuck | 0:aad43948c45c | 527 | |
dudmuck | 0:aad43948c45c | 528 | /** |
dudmuck | 1:b497f235115a | 529 | * Convert parameter to integer |
dudmuck | 1:b497f235115a | 530 | * @param context |
dudmuck | 1:b497f235115a | 531 | * @param parameter |
dudmuck | 1:b497f235115a | 532 | * @param value result |
dudmuck | 1:b497f235115a | 533 | * @return TRUE if succesful |
dudmuck | 1:b497f235115a | 534 | */ |
dudmuck | 1:b497f235115a | 535 | scpi_bool_t SCPI_ParamToInt(scpi_t * context, scpi_parameter_t * parameter, int32_t * value) { |
dudmuck | 1:b497f235115a | 536 | |
dudmuck | 1:b497f235115a | 537 | if (!value) { |
dudmuck | 1:b497f235115a | 538 | SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); |
dudmuck | 1:b497f235115a | 539 | return FALSE; |
dudmuck | 1:b497f235115a | 540 | } |
dudmuck | 1:b497f235115a | 541 | |
dudmuck | 1:b497f235115a | 542 | switch (parameter->type) { |
dudmuck | 1:b497f235115a | 543 | case SCPI_TOKEN_HEXNUM: |
dudmuck | 1:b497f235115a | 544 | return strToLong(parameter->ptr, value, 16) > 0 ? TRUE : FALSE; |
dudmuck | 1:b497f235115a | 545 | case SCPI_TOKEN_OCTNUM: |
dudmuck | 1:b497f235115a | 546 | return strToLong(parameter->ptr, value, 8) > 0 ? TRUE : FALSE; |
dudmuck | 1:b497f235115a | 547 | case SCPI_TOKEN_BINNUM: |
dudmuck | 1:b497f235115a | 548 | return strToLong(parameter->ptr, value, 2) > 0 ? TRUE : FALSE; |
dudmuck | 1:b497f235115a | 549 | case SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA: |
dudmuck | 1:b497f235115a | 550 | case SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA_WITH_SUFFIX: |
dudmuck | 1:b497f235115a | 551 | return strToLong(parameter->ptr, value, 10) > 0 ? TRUE : FALSE; |
dudmuck | 1:b497f235115a | 552 | } |
dudmuck | 1:b497f235115a | 553 | return FALSE; |
dudmuck | 1:b497f235115a | 554 | } |
dudmuck | 1:b497f235115a | 555 | |
dudmuck | 1:b497f235115a | 556 | /** |
dudmuck | 1:b497f235115a | 557 | * Convert parameter to double |
dudmuck | 1:b497f235115a | 558 | * @param context |
dudmuck | 1:b497f235115a | 559 | * @param parameter |
dudmuck | 1:b497f235115a | 560 | * @param value result |
dudmuck | 1:b497f235115a | 561 | * @return TRUE if succesful |
dudmuck | 1:b497f235115a | 562 | */ |
dudmuck | 1:b497f235115a | 563 | scpi_bool_t SCPI_ParamToDouble(scpi_t * context, scpi_parameter_t * parameter, double * value) { |
dudmuck | 1:b497f235115a | 564 | scpi_bool_t result = FALSE; |
dudmuck | 1:b497f235115a | 565 | int32_t valint; |
dudmuck | 1:b497f235115a | 566 | |
dudmuck | 1:b497f235115a | 567 | if (!value) { |
dudmuck | 1:b497f235115a | 568 | SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); |
dudmuck | 1:b497f235115a | 569 | return FALSE; |
dudmuck | 1:b497f235115a | 570 | } |
dudmuck | 1:b497f235115a | 571 | |
dudmuck | 1:b497f235115a | 572 | switch (parameter->type) { |
dudmuck | 1:b497f235115a | 573 | case SCPI_TOKEN_HEXNUM: |
dudmuck | 1:b497f235115a | 574 | case SCPI_TOKEN_OCTNUM: |
dudmuck | 1:b497f235115a | 575 | case SCPI_TOKEN_BINNUM: |
dudmuck | 1:b497f235115a | 576 | result = SCPI_ParamToInt(context, parameter, &valint); |
dudmuck | 1:b497f235115a | 577 | *value = valint; |
dudmuck | 1:b497f235115a | 578 | break; |
dudmuck | 1:b497f235115a | 579 | case SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA: |
dudmuck | 1:b497f235115a | 580 | case SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA_WITH_SUFFIX: |
dudmuck | 1:b497f235115a | 581 | result = strToDouble(parameter->ptr, value) > 0 ? TRUE : FALSE; |
dudmuck | 1:b497f235115a | 582 | break; |
dudmuck | 1:b497f235115a | 583 | } |
dudmuck | 1:b497f235115a | 584 | return result; |
dudmuck | 1:b497f235115a | 585 | } |
dudmuck | 1:b497f235115a | 586 | |
dudmuck | 1:b497f235115a | 587 | /** |
dudmuck | 1:b497f235115a | 588 | * Read floating point parameter |
dudmuck | 0:aad43948c45c | 589 | * @param context |
dudmuck | 0:aad43948c45c | 590 | * @param value |
dudmuck | 0:aad43948c45c | 591 | * @param mandatory |
dudmuck | 1:b497f235115a | 592 | * @return |
dudmuck | 0:aad43948c45c | 593 | */ |
dudmuck | 1:b497f235115a | 594 | scpi_bool_t SCPI_ParamDouble(scpi_t * context, double * value, scpi_bool_t mandatory) { |
dudmuck | 1:b497f235115a | 595 | scpi_bool_t result; |
dudmuck | 1:b497f235115a | 596 | scpi_parameter_t param; |
dudmuck | 0:aad43948c45c | 597 | |
dudmuck | 0:aad43948c45c | 598 | if (!value) { |
dudmuck | 1:b497f235115a | 599 | SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); |
dudmuck | 0:aad43948c45c | 600 | return FALSE; |
dudmuck | 0:aad43948c45c | 601 | } |
dudmuck | 0:aad43948c45c | 602 | |
dudmuck | 1:b497f235115a | 603 | result = SCPI_Parameter(context, ¶m, mandatory); |
dudmuck | 1:b497f235115a | 604 | if (result) { |
dudmuck | 1:b497f235115a | 605 | if (SCPI_ParamIsNumber(¶m, FALSE)) { |
dudmuck | 1:b497f235115a | 606 | SCPI_ParamToDouble(context, ¶m, value); |
dudmuck | 1:b497f235115a | 607 | } else if (SCPI_ParamIsNumber(¶m, TRUE)) { |
dudmuck | 1:b497f235115a | 608 | SCPI_ErrorPush(context, SCPI_ERROR_SUFFIX_NOT_ALLOWED); |
dudmuck | 1:b497f235115a | 609 | result = FALSE; |
dudmuck | 1:b497f235115a | 610 | } else { |
dudmuck | 1:b497f235115a | 611 | SCPI_ErrorPush(context, SCPI_ERROR_DATA_TYPE_ERROR); |
dudmuck | 1:b497f235115a | 612 | result = FALSE; |
dudmuck | 1:b497f235115a | 613 | } |
dudmuck | 0:aad43948c45c | 614 | } |
dudmuck | 1:b497f235115a | 615 | return result; |
dudmuck | 0:aad43948c45c | 616 | } |
dudmuck | 0:aad43948c45c | 617 | |
dudmuck | 0:aad43948c45c | 618 | /** |
dudmuck | 1:b497f235115a | 619 | * Read integer parameter |
dudmuck | 0:aad43948c45c | 620 | * @param context |
dudmuck | 0:aad43948c45c | 621 | * @param value |
dudmuck | 0:aad43948c45c | 622 | * @param mandatory |
dudmuck | 1:b497f235115a | 623 | * @return |
dudmuck | 0:aad43948c45c | 624 | */ |
dudmuck | 1:b497f235115a | 625 | scpi_bool_t SCPI_ParamInt(scpi_t * context, int32_t * value, scpi_bool_t mandatory) { |
dudmuck | 1:b497f235115a | 626 | scpi_bool_t result; |
dudmuck | 1:b497f235115a | 627 | scpi_parameter_t param; |
dudmuck | 0:aad43948c45c | 628 | |
dudmuck | 0:aad43948c45c | 629 | if (!value) { |
dudmuck | 1:b497f235115a | 630 | SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); |
dudmuck | 0:aad43948c45c | 631 | return FALSE; |
dudmuck | 0:aad43948c45c | 632 | } |
dudmuck | 0:aad43948c45c | 633 | |
dudmuck | 1:b497f235115a | 634 | result = SCPI_Parameter(context, ¶m, mandatory); |
dudmuck | 1:b497f235115a | 635 | if (result) { |
dudmuck | 1:b497f235115a | 636 | if (SCPI_ParamIsNumber(¶m, FALSE)) { |
dudmuck | 1:b497f235115a | 637 | SCPI_ParamToInt(context, ¶m, value); |
dudmuck | 1:b497f235115a | 638 | } else if (SCPI_ParamIsNumber(¶m, TRUE)) { |
dudmuck | 1:b497f235115a | 639 | SCPI_ErrorPush(context, SCPI_ERROR_SUFFIX_NOT_ALLOWED); |
dudmuck | 1:b497f235115a | 640 | result = FALSE; |
dudmuck | 1:b497f235115a | 641 | } else { |
dudmuck | 1:b497f235115a | 642 | SCPI_ErrorPush(context, SCPI_ERROR_DATA_TYPE_ERROR); |
dudmuck | 1:b497f235115a | 643 | result = FALSE; |
dudmuck | 1:b497f235115a | 644 | } |
dudmuck | 1:b497f235115a | 645 | } |
dudmuck | 1:b497f235115a | 646 | return result; |
dudmuck | 1:b497f235115a | 647 | } |
dudmuck | 1:b497f235115a | 648 | |
dudmuck | 1:b497f235115a | 649 | /** |
dudmuck | 1:b497f235115a | 650 | * Read character parameter |
dudmuck | 1:b497f235115a | 651 | * @param context |
dudmuck | 1:b497f235115a | 652 | * @param value |
dudmuck | 1:b497f235115a | 653 | * @param len |
dudmuck | 1:b497f235115a | 654 | * @param mandatory |
dudmuck | 1:b497f235115a | 655 | * @return |
dudmuck | 1:b497f235115a | 656 | */ |
dudmuck | 1:b497f235115a | 657 | scpi_bool_t SCPI_ParamCharacters(scpi_t * context, const char ** value, size_t * len, scpi_bool_t mandatory) { |
dudmuck | 1:b497f235115a | 658 | scpi_bool_t result; |
dudmuck | 1:b497f235115a | 659 | scpi_parameter_t param; |
dudmuck | 1:b497f235115a | 660 | |
dudmuck | 1:b497f235115a | 661 | if (!value || !len) { |
dudmuck | 1:b497f235115a | 662 | SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); |
dudmuck | 0:aad43948c45c | 663 | return FALSE; |
dudmuck | 0:aad43948c45c | 664 | } |
dudmuck | 0:aad43948c45c | 665 | |
dudmuck | 1:b497f235115a | 666 | result = SCPI_Parameter(context, ¶m, mandatory); |
dudmuck | 1:b497f235115a | 667 | if (result) { |
dudmuck | 1:b497f235115a | 668 | *value = param.ptr; |
dudmuck | 1:b497f235115a | 669 | *len = param.len; |
dudmuck | 0:aad43948c45c | 670 | |
dudmuck | 1:b497f235115a | 671 | // TODO: return also parameter type (ProgramMnemonic, ArbitraryBlockProgramData, SingleQuoteProgramData, DoubleQuoteProgramData |
dudmuck | 0:aad43948c45c | 672 | } |
dudmuck | 0:aad43948c45c | 673 | |
dudmuck | 1:b497f235115a | 674 | return result; |
dudmuck | 0:aad43948c45c | 675 | } |
dudmuck | 0:aad43948c45c | 676 | |
dudmuck | 0:aad43948c45c | 677 | /** |
dudmuck | 1:b497f235115a | 678 | * Get arbitrary block program data and returns pointer to data |
dudmuck | 0:aad43948c45c | 679 | * @param context |
dudmuck | 1:b497f235115a | 680 | * @param value result pointer to data |
dudmuck | 1:b497f235115a | 681 | * @param len result length of data |
dudmuck | 0:aad43948c45c | 682 | * @param mandatory |
dudmuck | 1:b497f235115a | 683 | * @return |
dudmuck | 0:aad43948c45c | 684 | */ |
dudmuck | 1:b497f235115a | 685 | scpi_bool_t SCPI_ParamArbitraryBlock(scpi_t * context, const char ** value, size_t * len, scpi_bool_t mandatory) { |
dudmuck | 1:b497f235115a | 686 | scpi_bool_t result; |
dudmuck | 1:b497f235115a | 687 | scpi_parameter_t param; |
dudmuck | 0:aad43948c45c | 688 | |
dudmuck | 0:aad43948c45c | 689 | if (!value || !len) { |
dudmuck | 1:b497f235115a | 690 | SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); |
dudmuck | 1:b497f235115a | 691 | return FALSE; |
dudmuck | 1:b497f235115a | 692 | } |
dudmuck | 1:b497f235115a | 693 | |
dudmuck | 1:b497f235115a | 694 | result = SCPI_Parameter(context, ¶m, mandatory); |
dudmuck | 1:b497f235115a | 695 | if (result) { |
dudmuck | 1:b497f235115a | 696 | if (param.type == SCPI_TOKEN_ARBITRARY_BLOCK_PROGRAM_DATA) { |
dudmuck | 1:b497f235115a | 697 | *value = param.ptr; |
dudmuck | 1:b497f235115a | 698 | *len = param.len; |
dudmuck | 1:b497f235115a | 699 | } else { |
dudmuck | 1:b497f235115a | 700 | SCPI_ErrorPush(context, SCPI_ERROR_DATA_TYPE_ERROR); |
dudmuck | 1:b497f235115a | 701 | result = FALSE; |
dudmuck | 1:b497f235115a | 702 | } |
dudmuck | 1:b497f235115a | 703 | } |
dudmuck | 1:b497f235115a | 704 | |
dudmuck | 1:b497f235115a | 705 | return result; |
dudmuck | 1:b497f235115a | 706 | } |
dudmuck | 1:b497f235115a | 707 | |
dudmuck | 1:b497f235115a | 708 | scpi_bool_t SCPI_ParamCopyText(scpi_t * context, char * buffer, size_t buffer_len, size_t * copy_len, scpi_bool_t mandatory) { |
dudmuck | 1:b497f235115a | 709 | scpi_bool_t result; |
dudmuck | 1:b497f235115a | 710 | scpi_parameter_t param; |
dudmuck | 1:b497f235115a | 711 | size_t i_from; |
dudmuck | 1:b497f235115a | 712 | size_t i_to; |
dudmuck | 1:b497f235115a | 713 | char quote; |
dudmuck | 1:b497f235115a | 714 | |
dudmuck | 1:b497f235115a | 715 | if (!buffer || !copy_len) { |
dudmuck | 1:b497f235115a | 716 | SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); |
dudmuck | 0:aad43948c45c | 717 | return FALSE; |
dudmuck | 0:aad43948c45c | 718 | } |
dudmuck | 0:aad43948c45c | 719 | |
dudmuck | 1:b497f235115a | 720 | result = SCPI_Parameter(context, ¶m, mandatory); |
dudmuck | 1:b497f235115a | 721 | if (result) { |
dudmuck | 1:b497f235115a | 722 | |
dudmuck | 1:b497f235115a | 723 | switch (param.type) { |
dudmuck | 1:b497f235115a | 724 | case SCPI_TOKEN_SINGLE_QUOTE_PROGRAM_DATA: |
dudmuck | 1:b497f235115a | 725 | case SCPI_TOKEN_DOUBLE_QUOTE_PROGRAM_DATA: |
dudmuck | 1:b497f235115a | 726 | quote = param.type == SCPI_TOKEN_SINGLE_QUOTE_PROGRAM_DATA ? '\'' : '"'; |
dudmuck | 1:b497f235115a | 727 | for (i_from = 0, i_to = 0; i_from < (size_t) param.len; i_from++) { |
dudmuck | 1:b497f235115a | 728 | if (i_from >= buffer_len) { |
dudmuck | 1:b497f235115a | 729 | break; |
dudmuck | 1:b497f235115a | 730 | } |
dudmuck | 1:b497f235115a | 731 | buffer[i_to] = param.ptr[i_from]; |
dudmuck | 1:b497f235115a | 732 | i_to++; |
dudmuck | 1:b497f235115a | 733 | if (param.ptr[i_from] == quote) { |
dudmuck | 1:b497f235115a | 734 | i_from++; |
dudmuck | 1:b497f235115a | 735 | } |
dudmuck | 1:b497f235115a | 736 | } |
dudmuck | 1:b497f235115a | 737 | break; |
dudmuck | 1:b497f235115a | 738 | default: |
dudmuck | 1:b497f235115a | 739 | SCPI_ErrorPush(context, SCPI_ERROR_DATA_TYPE_ERROR); |
dudmuck | 1:b497f235115a | 740 | result = FALSE; |
dudmuck | 1:b497f235115a | 741 | } |
dudmuck | 1:b497f235115a | 742 | } |
dudmuck | 1:b497f235115a | 743 | |
dudmuck | 1:b497f235115a | 744 | return result; |
dudmuck | 1:b497f235115a | 745 | } |
dudmuck | 1:b497f235115a | 746 | |
dudmuck | 1:b497f235115a | 747 | /** |
dudmuck | 1:b497f235115a | 748 | * Convert parameter to choice |
dudmuck | 1:b497f235115a | 749 | * @param context |
dudmuck | 1:b497f235115a | 750 | * @param parameter - should be PROGRAM_MNEMONIC |
dudmuck | 1:b497f235115a | 751 | * @param options - NULL terminated list of choices |
dudmuck | 1:b497f235115a | 752 | * @param value - index to options |
dudmuck | 1:b497f235115a | 753 | * @return |
dudmuck | 1:b497f235115a | 754 | */ |
dudmuck | 1:b497f235115a | 755 | scpi_bool_t SCPI_ParamToChoice(scpi_t * context, scpi_parameter_t * parameter, const scpi_choice_def_t * options, int32_t * value) { |
dudmuck | 1:b497f235115a | 756 | size_t res; |
dudmuck | 1:b497f235115a | 757 | scpi_bool_t result = FALSE; |
dudmuck | 1:b497f235115a | 758 | |
dudmuck | 1:b497f235115a | 759 | if (!options || !value) { |
dudmuck | 1:b497f235115a | 760 | SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); |
dudmuck | 0:aad43948c45c | 761 | return FALSE; |
dudmuck | 0:aad43948c45c | 762 | } |
dudmuck | 0:aad43948c45c | 763 | |
dudmuck | 1:b497f235115a | 764 | if (parameter->type == SCPI_TOKEN_PROGRAM_MNEMONIC) { |
dudmuck | 1:b497f235115a | 765 | for (res = 0; options[res].name; ++res) { |
dudmuck | 1:b497f235115a | 766 | if (matchPattern(options[res].name, strlen(options[res].name), parameter->ptr, parameter->len, NULL)) { |
dudmuck | 1:b497f235115a | 767 | *value = options[res].tag; |
dudmuck | 1:b497f235115a | 768 | result = TRUE; |
dudmuck | 1:b497f235115a | 769 | break; |
dudmuck | 1:b497f235115a | 770 | } |
dudmuck | 1:b497f235115a | 771 | } |
dudmuck | 1:b497f235115a | 772 | |
dudmuck | 1:b497f235115a | 773 | if (!result) { |
dudmuck | 1:b497f235115a | 774 | SCPI_ErrorPush(context, SCPI_ERROR_ILLEGAL_PARAMETER_VALUE); |
dudmuck | 0:aad43948c45c | 775 | } |
dudmuck | 1:b497f235115a | 776 | } else { |
dudmuck | 1:b497f235115a | 777 | SCPI_ErrorPush(context, SCPI_ERROR_DATA_TYPE_ERROR); |
dudmuck | 1:b497f235115a | 778 | } |
dudmuck | 1:b497f235115a | 779 | |
dudmuck | 1:b497f235115a | 780 | return result; |
dudmuck | 1:b497f235115a | 781 | } |
dudmuck | 1:b497f235115a | 782 | |
dudmuck | 1:b497f235115a | 783 | /** |
dudmuck | 1:b497f235115a | 784 | * Find tag in choices and returns its first textual representation |
dudmuck | 1:b497f235115a | 785 | * @param options specifications of choices numbers (patterns) |
dudmuck | 1:b497f235115a | 786 | * @param tag numerical representatio of choice |
dudmuck | 1:b497f235115a | 787 | * @param text result text |
dudmuck | 1:b497f235115a | 788 | * @return TRUE if succesfule, else FALSE |
dudmuck | 1:b497f235115a | 789 | */ |
dudmuck | 1:b497f235115a | 790 | scpi_bool_t SCPI_ChoiceToName(const scpi_choice_def_t * options, int32_t tag, const char ** text) { |
dudmuck | 1:b497f235115a | 791 | int i; |
dudmuck | 1:b497f235115a | 792 | |
dudmuck | 1:b497f235115a | 793 | for (i = 0; options[i].name != NULL; i++) { |
dudmuck | 1:b497f235115a | 794 | if (options[i].tag == tag) { |
dudmuck | 1:b497f235115a | 795 | *text = options[i].name; |
dudmuck | 1:b497f235115a | 796 | return TRUE; |
dudmuck | 1:b497f235115a | 797 | } |
dudmuck | 0:aad43948c45c | 798 | } |
dudmuck | 0:aad43948c45c | 799 | |
dudmuck | 0:aad43948c45c | 800 | return FALSE; |
dudmuck | 0:aad43948c45c | 801 | } |
dudmuck | 0:aad43948c45c | 802 | |
dudmuck | 0:aad43948c45c | 803 | /** |
dudmuck | 1:b497f235115a | 804 | * Read BOOL parameter (0,1,ON,OFF) |
dudmuck | 0:aad43948c45c | 805 | * @param context |
dudmuck | 0:aad43948c45c | 806 | * @param value |
dudmuck | 0:aad43948c45c | 807 | * @param mandatory |
dudmuck | 1:b497f235115a | 808 | * @return |
dudmuck | 0:aad43948c45c | 809 | */ |
dudmuck | 0:aad43948c45c | 810 | scpi_bool_t SCPI_ParamBool(scpi_t * context, scpi_bool_t * value, scpi_bool_t mandatory) { |
dudmuck | 1:b497f235115a | 811 | scpi_bool_t result; |
dudmuck | 1:b497f235115a | 812 | scpi_parameter_t param; |
dudmuck | 1:b497f235115a | 813 | int32_t intval; |
dudmuck | 1:b497f235115a | 814 | |
dudmuck | 1:b497f235115a | 815 | scpi_choice_def_t bool_options[] = { |
dudmuck | 1:b497f235115a | 816 | {"OFF", 0}, |
dudmuck | 1:b497f235115a | 817 | {"ON", 1}, |
dudmuck | 1:b497f235115a | 818 | SCPI_CHOICE_LIST_END /* termination of option list */ |
dudmuck | 1:b497f235115a | 819 | }; |
dudmuck | 0:aad43948c45c | 820 | |
dudmuck | 0:aad43948c45c | 821 | if (!value) { |
dudmuck | 1:b497f235115a | 822 | SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); |
dudmuck | 0:aad43948c45c | 823 | return FALSE; |
dudmuck | 0:aad43948c45c | 824 | } |
dudmuck | 0:aad43948c45c | 825 | |
dudmuck | 1:b497f235115a | 826 | result = SCPI_Parameter(context, ¶m, mandatory); |
dudmuck | 0:aad43948c45c | 827 | |
dudmuck | 1:b497f235115a | 828 | if (result) { |
dudmuck | 1:b497f235115a | 829 | if (param.type == SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA) { |
dudmuck | 1:b497f235115a | 830 | SCPI_ParamToInt(context, ¶m, &intval); |
dudmuck | 1:b497f235115a | 831 | *value = intval ? TRUE : FALSE; |
dudmuck | 1:b497f235115a | 832 | } else { |
dudmuck | 1:b497f235115a | 833 | result = SCPI_ParamToChoice(context, ¶m, bool_options, &intval); |
dudmuck | 1:b497f235115a | 834 | if (result) { |
dudmuck | 1:b497f235115a | 835 | *value = intval ? TRUE : FALSE; |
dudmuck | 1:b497f235115a | 836 | } |
dudmuck | 0:aad43948c45c | 837 | } |
dudmuck | 0:aad43948c45c | 838 | } |
dudmuck | 0:aad43948c45c | 839 | |
dudmuck | 1:b497f235115a | 840 | return result; |
dudmuck | 0:aad43948c45c | 841 | } |
dudmuck | 0:aad43948c45c | 842 | |
dudmuck | 0:aad43948c45c | 843 | /** |
dudmuck | 1:b497f235115a | 844 | * Read value from list of options |
dudmuck | 0:aad43948c45c | 845 | * @param context |
dudmuck | 0:aad43948c45c | 846 | * @param options |
dudmuck | 0:aad43948c45c | 847 | * @param value |
dudmuck | 0:aad43948c45c | 848 | * @param mandatory |
dudmuck | 1:b497f235115a | 849 | * @return |
dudmuck | 0:aad43948c45c | 850 | */ |
dudmuck | 1:b497f235115a | 851 | scpi_bool_t SCPI_ParamChoice(scpi_t * context, const scpi_choice_def_t * options, int32_t * value, scpi_bool_t mandatory) { |
dudmuck | 1:b497f235115a | 852 | scpi_bool_t result; |
dudmuck | 1:b497f235115a | 853 | scpi_parameter_t param; |
dudmuck | 0:aad43948c45c | 854 | |
dudmuck | 0:aad43948c45c | 855 | if (!options || !value) { |
dudmuck | 1:b497f235115a | 856 | SCPI_ErrorPush(context, SCPI_ERROR_SYSTEM_ERROR); |
dudmuck | 0:aad43948c45c | 857 | return FALSE; |
dudmuck | 0:aad43948c45c | 858 | } |
dudmuck | 0:aad43948c45c | 859 | |
dudmuck | 1:b497f235115a | 860 | result = SCPI_Parameter(context, ¶m, mandatory); |
dudmuck | 1:b497f235115a | 861 | if (result) { |
dudmuck | 1:b497f235115a | 862 | result = SCPI_ParamToChoice(context, ¶m, options, value); |
dudmuck | 1:b497f235115a | 863 | } |
dudmuck | 1:b497f235115a | 864 | |
dudmuck | 1:b497f235115a | 865 | return result; |
dudmuck | 1:b497f235115a | 866 | } |
dudmuck | 1:b497f235115a | 867 | |
dudmuck | 1:b497f235115a | 868 | /** |
dudmuck | 1:b497f235115a | 869 | * Parse one parameter and detect type |
dudmuck | 1:b497f235115a | 870 | * @param state |
dudmuck | 1:b497f235115a | 871 | * @param token |
dudmuck | 1:b497f235115a | 872 | * @return |
dudmuck | 1:b497f235115a | 873 | */ |
dudmuck | 1:b497f235115a | 874 | int scpiParser_parseProgramData(lex_state_t * state, scpi_token_t * token) { |
dudmuck | 1:b497f235115a | 875 | scpi_token_t tmp; |
dudmuck | 1:b497f235115a | 876 | int result = 0; |
dudmuck | 1:b497f235115a | 877 | int wsLen; |
dudmuck | 1:b497f235115a | 878 | int suffixLen; |
dudmuck | 1:b497f235115a | 879 | int realLen = 0; |
dudmuck | 1:b497f235115a | 880 | realLen += scpiLex_WhiteSpace(state, &tmp); |
dudmuck | 1:b497f235115a | 881 | |
dudmuck | 1:b497f235115a | 882 | if (result == 0) result = scpiLex_NondecimalNumericData(state, token); |
dudmuck | 1:b497f235115a | 883 | if (result == 0) result = scpiLex_CharacterProgramData(state, token); |
dudmuck | 1:b497f235115a | 884 | if (result == 0) { |
dudmuck | 1:b497f235115a | 885 | result = scpiLex_DecimalNumericProgramData(state, token); |
dudmuck | 1:b497f235115a | 886 | if (result != 0) { |
dudmuck | 1:b497f235115a | 887 | wsLen = scpiLex_WhiteSpace(state, &tmp); |
dudmuck | 1:b497f235115a | 888 | suffixLen = scpiLex_SuffixProgramData(state, &tmp); |
dudmuck | 1:b497f235115a | 889 | if (suffixLen > 0) { |
dudmuck | 1:b497f235115a | 890 | token->len += wsLen + suffixLen; |
dudmuck | 1:b497f235115a | 891 | token->type = SCPI_TOKEN_DECIMAL_NUMERIC_PROGRAM_DATA_WITH_SUFFIX; |
dudmuck | 1:b497f235115a | 892 | result = token->len; |
dudmuck | 1:b497f235115a | 893 | } |
dudmuck | 0:aad43948c45c | 894 | } |
dudmuck | 0:aad43948c45c | 895 | } |
dudmuck | 0:aad43948c45c | 896 | |
dudmuck | 1:b497f235115a | 897 | if (result == 0) result = scpiLex_StringProgramData(state, token); |
dudmuck | 1:b497f235115a | 898 | if (result == 0) result = scpiLex_ArbitraryBlockProgramData(state, token); |
dudmuck | 1:b497f235115a | 899 | if (result == 0) result = scpiLex_ProgramExpression(state, token); |
dudmuck | 1:b497f235115a | 900 | |
dudmuck | 1:b497f235115a | 901 | realLen += scpiLex_WhiteSpace(state, &tmp); |
dudmuck | 1:b497f235115a | 902 | |
dudmuck | 1:b497f235115a | 903 | return result + realLen; |
dudmuck | 1:b497f235115a | 904 | } |
dudmuck | 1:b497f235115a | 905 | |
dudmuck | 1:b497f235115a | 906 | /** |
dudmuck | 1:b497f235115a | 907 | * Skip all parameters to correctly detect end of command line. |
dudmuck | 1:b497f235115a | 908 | * @param state |
dudmuck | 1:b497f235115a | 909 | * @param token |
dudmuck | 1:b497f235115a | 910 | * @param numberOfParameters |
dudmuck | 1:b497f235115a | 911 | * @return |
dudmuck | 1:b497f235115a | 912 | */ |
dudmuck | 1:b497f235115a | 913 | int scpiParser_parseAllProgramData(lex_state_t * state, scpi_token_t * token, int * numberOfParameters) { |
dudmuck | 1:b497f235115a | 914 | |
dudmuck | 1:b497f235115a | 915 | int result; |
dudmuck | 1:b497f235115a | 916 | scpi_token_t tmp; |
dudmuck | 1:b497f235115a | 917 | int paramCount = 0; |
dudmuck | 1:b497f235115a | 918 | |
dudmuck | 1:b497f235115a | 919 | token->len = -1; |
dudmuck | 1:b497f235115a | 920 | token->type = SCPI_TOKEN_ALL_PROGRAM_DATA; |
dudmuck | 1:b497f235115a | 921 | token->ptr = state->pos; |
dudmuck | 1:b497f235115a | 922 | |
dudmuck | 1:b497f235115a | 923 | |
dudmuck | 1:b497f235115a | 924 | for (result = 1; result != 0; result = scpiLex_Comma(state, &tmp)) { |
dudmuck | 1:b497f235115a | 925 | token->len += result; |
dudmuck | 1:b497f235115a | 926 | |
dudmuck | 1:b497f235115a | 927 | if (result == 0) { |
dudmuck | 1:b497f235115a | 928 | token->type = SCPI_TOKEN_UNKNOWN; |
dudmuck | 1:b497f235115a | 929 | token->len = 0; |
dudmuck | 1:b497f235115a | 930 | paramCount = -1; |
dudmuck | 1:b497f235115a | 931 | break; |
dudmuck | 1:b497f235115a | 932 | } |
dudmuck | 1:b497f235115a | 933 | |
dudmuck | 1:b497f235115a | 934 | result = scpiParser_parseProgramData(state, &tmp); |
dudmuck | 1:b497f235115a | 935 | if (tmp.type != SCPI_TOKEN_UNKNOWN) { |
dudmuck | 1:b497f235115a | 936 | token->len += result; |
dudmuck | 1:b497f235115a | 937 | } else { |
dudmuck | 1:b497f235115a | 938 | token->type = SCPI_TOKEN_UNKNOWN; |
dudmuck | 1:b497f235115a | 939 | token->len = 0; |
dudmuck | 1:b497f235115a | 940 | paramCount = -1; |
dudmuck | 1:b497f235115a | 941 | break; |
dudmuck | 1:b497f235115a | 942 | } |
dudmuck | 1:b497f235115a | 943 | paramCount++; |
dudmuck | 1:b497f235115a | 944 | } |
dudmuck | 1:b497f235115a | 945 | |
dudmuck | 1:b497f235115a | 946 | if (token->len == -1) { |
dudmuck | 1:b497f235115a | 947 | token->len = 0; |
dudmuck | 1:b497f235115a | 948 | } |
dudmuck | 1:b497f235115a | 949 | |
dudmuck | 1:b497f235115a | 950 | if (numberOfParameters != NULL) { |
dudmuck | 1:b497f235115a | 951 | *numberOfParameters = paramCount; |
dudmuck | 1:b497f235115a | 952 | } |
dudmuck | 1:b497f235115a | 953 | return token->len; |
dudmuck | 0:aad43948c45c | 954 | } |
dudmuck | 0:aad43948c45c | 955 | |
dudmuck | 1:b497f235115a | 956 | /** |
dudmuck | 1:b497f235115a | 957 | * Skip complete command line - program header and parameters |
dudmuck | 1:b497f235115a | 958 | * @param state |
dudmuck | 1:b497f235115a | 959 | * @param buffer |
dudmuck | 1:b497f235115a | 960 | * @param len |
dudmuck | 1:b497f235115a | 961 | * @return |
dudmuck | 1:b497f235115a | 962 | */ |
dudmuck | 1:b497f235115a | 963 | int scpiParser_detectProgramMessageUnit(scpi_parser_state_t * state, char * buffer, int len) { |
dudmuck | 1:b497f235115a | 964 | lex_state_t lex_state; |
dudmuck | 1:b497f235115a | 965 | scpi_token_t tmp; |
dudmuck | 1:b497f235115a | 966 | int result = 0; |
dudmuck | 1:b497f235115a | 967 | |
dudmuck | 1:b497f235115a | 968 | lex_state.buffer = lex_state.pos = buffer; |
dudmuck | 1:b497f235115a | 969 | lex_state.len = len; |
dudmuck | 1:b497f235115a | 970 | state->numberOfParameters = 0; |
dudmuck | 1:b497f235115a | 971 | |
dudmuck | 1:b497f235115a | 972 | /* ignore whitespace at the begginig */ |
dudmuck | 1:b497f235115a | 973 | scpiLex_WhiteSpace(&lex_state, &tmp); |
dudmuck | 1:b497f235115a | 974 | |
dudmuck | 1:b497f235115a | 975 | if (scpiLex_ProgramHeader(&lex_state, &state->programHeader) >= 0) { |
dudmuck | 1:b497f235115a | 976 | if (scpiLex_WhiteSpace(&lex_state, &tmp) > 0) { |
dudmuck | 1:b497f235115a | 977 | scpiParser_parseAllProgramData(&lex_state, &state->programData, &state->numberOfParameters); |
dudmuck | 1:b497f235115a | 978 | } else { |
dudmuck | 1:b497f235115a | 979 | invalidateToken(&state->programData, lex_state.pos); |
dudmuck | 1:b497f235115a | 980 | } |
dudmuck | 1:b497f235115a | 981 | } else { |
dudmuck | 1:b497f235115a | 982 | invalidateToken(&state->programHeader, lex_state.buffer); |
dudmuck | 1:b497f235115a | 983 | invalidateToken(&state->programData, lex_state.buffer); |
dudmuck | 1:b497f235115a | 984 | } |
dudmuck | 1:b497f235115a | 985 | |
dudmuck | 1:b497f235115a | 986 | if (result == 0) result = scpiLex_NewLine(&lex_state, &tmp); |
dudmuck | 1:b497f235115a | 987 | if (result == 0) result = scpiLex_Semicolon(&lex_state, &tmp); |
dudmuck | 1:b497f235115a | 988 | |
dudmuck | 1:b497f235115a | 989 | if (!scpiLex_IsEos(&lex_state) && (result == 0)) { |
dudmuck | 1:b497f235115a | 990 | lex_state.pos++; |
dudmuck | 1:b497f235115a | 991 | |
dudmuck | 1:b497f235115a | 992 | state->programHeader.len = 1; |
dudmuck | 1:b497f235115a | 993 | state->programHeader.type = SCPI_TOKEN_INVALID; |
dudmuck | 1:b497f235115a | 994 | |
dudmuck | 1:b497f235115a | 995 | invalidateToken(&state->programData, lex_state.buffer); |
dudmuck | 1:b497f235115a | 996 | } |
dudmuck | 1:b497f235115a | 997 | |
dudmuck | 1:b497f235115a | 998 | if (SCPI_TOKEN_SEMICOLON == tmp.type) { |
dudmuck | 1:b497f235115a | 999 | state->termination = SCPI_MESSAGE_TERMINATION_SEMICOLON; |
dudmuck | 1:b497f235115a | 1000 | } else if (SCPI_TOKEN_NL == tmp.type) { |
dudmuck | 1:b497f235115a | 1001 | state->termination = SCPI_MESSAGE_TERMINATION_NL; |
dudmuck | 1:b497f235115a | 1002 | } else { |
dudmuck | 1:b497f235115a | 1003 | state->termination = SCPI_MESSAGE_TERMINATION_NONE; |
dudmuck | 1:b497f235115a | 1004 | } |
dudmuck | 1:b497f235115a | 1005 | |
dudmuck | 1:b497f235115a | 1006 | return lex_state.pos - lex_state.buffer; |
dudmuck | 1:b497f235115a | 1007 | } |
dudmuck | 1:b497f235115a | 1008 | |
dudmuck | 1:b497f235115a | 1009 | /** |
dudmuck | 1:b497f235115a | 1010 | * Check current command |
dudmuck | 1:b497f235115a | 1011 | * - suitable for one handle to multiple commands |
dudmuck | 1:b497f235115a | 1012 | * @param context |
dudmuck | 1:b497f235115a | 1013 | * @param cmd |
dudmuck | 1:b497f235115a | 1014 | * @return |
dudmuck | 1:b497f235115a | 1015 | */ |
dudmuck | 0:aad43948c45c | 1016 | scpi_bool_t SCPI_IsCmd(scpi_t * context, const char * cmd) { |
dudmuck | 1:b497f235115a | 1017 | const char * pattern; |
dudmuck | 1:b497f235115a | 1018 | |
dudmuck | 1:b497f235115a | 1019 | if (!context->param_list.cmd) { |
dudmuck | 0:aad43948c45c | 1020 | return FALSE; |
dudmuck | 0:aad43948c45c | 1021 | } |
dudmuck | 0:aad43948c45c | 1022 | |
dudmuck | 1:b497f235115a | 1023 | pattern = context->param_list.cmd->pattern; |
dudmuck | 1:b497f235115a | 1024 | return matchCommand (pattern, cmd, strlen (cmd), NULL, 0); |
dudmuck | 0:aad43948c45c | 1025 | } |
dudmuck | 1:b497f235115a | 1026 | |
dudmuck | 1:b497f235115a | 1027 | /** |
dudmuck | 1:b497f235115a | 1028 | * Return the .tag field of the matching scpi_command_t |
dudmuck | 1:b497f235115a | 1029 | * @param context |
dudmuck | 1:b497f235115a | 1030 | * @return |
dudmuck | 1:b497f235115a | 1031 | */ |
dudmuck | 1:b497f235115a | 1032 | int32_t SCPI_CmdTag(scpi_t * context) { |
dudmuck | 1:b497f235115a | 1033 | if (context->param_list.cmd) { |
dudmuck | 1:b497f235115a | 1034 | return context->param_list.cmd->tag; |
dudmuck | 1:b497f235115a | 1035 | } else { |
dudmuck | 1:b497f235115a | 1036 | return 0; |
dudmuck | 1:b497f235115a | 1037 | } |
dudmuck | 1:b497f235115a | 1038 | } |
dudmuck | 1:b497f235115a | 1039 | |
dudmuck | 1:b497f235115a | 1040 | scpi_bool_t SCPI_Match(const char * pattern, const char * value, size_t len) { |
dudmuck | 1:b497f235115a | 1041 | return matchCommand (pattern, value, len, NULL, 0); |
dudmuck | 1:b497f235115a | 1042 | } |
dudmuck | 1:b497f235115a | 1043 | |
dudmuck | 1:b497f235115a | 1044 | scpi_bool_t SCPI_CommandNumbers(scpi_t * context, int32_t * numbers, size_t len) { |
dudmuck | 1:b497f235115a | 1045 | return matchCommand (context->param_list.cmd->pattern, context->param_list.cmd_raw.data, context->param_list.cmd_raw.length, numbers, len); |
dudmuck | 1:b497f235115a | 1046 | } |