https://github.com/j123b567/scpi-parser
Dependents: scpi_sx127x scpi_sx127x_firstTest MLX90418_I2C_master
src/utils.c@0:aad43948c45c, 2015-04-09 (annotated)
- Committer:
- dudmuck
- Date:
- Thu Apr 09 22:42:15 2015 +0000
- Revision:
- 0:aad43948c45c
- Child:
- 1:b497f235115a
SCPI library
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
dudmuck | 0:aad43948c45c | 1 | #define HAVE_STRNLEN 0 |
dudmuck | 0:aad43948c45c | 2 | /*- |
dudmuck | 0:aad43948c45c | 3 | * Copyright (c) 2013 Jan Breuer |
dudmuck | 0:aad43948c45c | 4 | * Richard.hmm |
dudmuck | 0:aad43948c45c | 5 | * Copyright (c) 2012 Jan Breuer |
dudmuck | 0:aad43948c45c | 6 | * |
dudmuck | 0:aad43948c45c | 7 | * All Rights Reserved |
dudmuck | 0:aad43948c45c | 8 | * |
dudmuck | 0:aad43948c45c | 9 | * Redistribution and use in source and binary forms, with or without |
dudmuck | 0:aad43948c45c | 10 | * modification, are permitted provided that the following conditions are |
dudmuck | 0:aad43948c45c | 11 | * met: |
dudmuck | 0:aad43948c45c | 12 | * 1. Redistributions of source code must retain the above copyright notice, |
dudmuck | 0:aad43948c45c | 13 | * this list of conditions and the following disclaimer. |
dudmuck | 0:aad43948c45c | 14 | * 2. Redistributions in binary form must reproduce the above copyright |
dudmuck | 0:aad43948c45c | 15 | * notice, this list of conditions and the following disclaimer in the |
dudmuck | 0:aad43948c45c | 16 | * documentation and/or other materials provided with the distribution. |
dudmuck | 0:aad43948c45c | 17 | * |
dudmuck | 0:aad43948c45c | 18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR |
dudmuck | 0:aad43948c45c | 19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
dudmuck | 0:aad43948c45c | 20 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
dudmuck | 0:aad43948c45c | 21 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE |
dudmuck | 0:aad43948c45c | 22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
dudmuck | 0:aad43948c45c | 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
dudmuck | 0:aad43948c45c | 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
dudmuck | 0:aad43948c45c | 25 | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
dudmuck | 0:aad43948c45c | 26 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
dudmuck | 0:aad43948c45c | 27 | * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
dudmuck | 0:aad43948c45c | 28 | * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
dudmuck | 0:aad43948c45c | 29 | */ |
dudmuck | 0:aad43948c45c | 30 | |
dudmuck | 0:aad43948c45c | 31 | /** |
dudmuck | 0:aad43948c45c | 32 | * @file scpi_utils.c |
dudmuck | 0:aad43948c45c | 33 | * @date Thu Nov 15 10:58:45 UTC 2012 |
dudmuck | 0:aad43948c45c | 34 | * |
dudmuck | 0:aad43948c45c | 35 | * @brief Conversion routines and string manipulation routines |
dudmuck | 0:aad43948c45c | 36 | * |
dudmuck | 0:aad43948c45c | 37 | * |
dudmuck | 0:aad43948c45c | 38 | */ |
dudmuck | 0:aad43948c45c | 39 | |
dudmuck | 0:aad43948c45c | 40 | #include <stdio.h> |
dudmuck | 0:aad43948c45c | 41 | #include <stdlib.h> |
dudmuck | 0:aad43948c45c | 42 | #include <string.h> |
dudmuck | 0:aad43948c45c | 43 | #include <ctype.h> |
dudmuck | 0:aad43948c45c | 44 | |
dudmuck | 0:aad43948c45c | 45 | #include "scpi/utils_private.h" |
dudmuck | 0:aad43948c45c | 46 | |
dudmuck | 0:aad43948c45c | 47 | static size_t patternSeparatorShortPos(const char * pattern, size_t len); |
dudmuck | 0:aad43948c45c | 48 | static size_t patternSeparatorPos(const char * pattern, size_t len); |
dudmuck | 0:aad43948c45c | 49 | static size_t cmdSeparatorPos(const char * cmd, size_t len); |
dudmuck | 0:aad43948c45c | 50 | |
dudmuck | 0:aad43948c45c | 51 | /** |
dudmuck | 0:aad43948c45c | 52 | * Find the first occurrence in str of a character in set. |
dudmuck | 0:aad43948c45c | 53 | * @param str |
dudmuck | 0:aad43948c45c | 54 | * @param size |
dudmuck | 0:aad43948c45c | 55 | * @param set |
dudmuck | 0:aad43948c45c | 56 | * @return |
dudmuck | 0:aad43948c45c | 57 | */ |
dudmuck | 0:aad43948c45c | 58 | const char * strnpbrk(const char *str, size_t size, const char *set) { |
dudmuck | 0:aad43948c45c | 59 | const char *scanp; |
dudmuck | 0:aad43948c45c | 60 | long c, sc; |
dudmuck | 0:aad43948c45c | 61 | const char * strend = str + size; |
dudmuck | 0:aad43948c45c | 62 | |
dudmuck | 0:aad43948c45c | 63 | while ((strend != str) && ((c = *str++) != 0)) { |
dudmuck | 0:aad43948c45c | 64 | for (scanp = set; (sc = *scanp++) != '\0';) |
dudmuck | 0:aad43948c45c | 65 | if (sc == c) |
dudmuck | 0:aad43948c45c | 66 | return str - 1; |
dudmuck | 0:aad43948c45c | 67 | } |
dudmuck | 0:aad43948c45c | 68 | return (NULL); |
dudmuck | 0:aad43948c45c | 69 | } |
dudmuck | 0:aad43948c45c | 70 | |
dudmuck | 0:aad43948c45c | 71 | /** |
dudmuck | 0:aad43948c45c | 72 | * Converts signed 32b integer value to string |
dudmuck | 0:aad43948c45c | 73 | * @param val integer value |
dudmuck | 0:aad43948c45c | 74 | * @param str converted textual representation |
dudmuck | 0:aad43948c45c | 75 | * @param len string buffer length |
dudmuck | 0:aad43948c45c | 76 | * @return number of bytes written to str (without '\0') |
dudmuck | 0:aad43948c45c | 77 | */ |
dudmuck | 0:aad43948c45c | 78 | size_t longToStr(int32_t val, char * str, size_t len) { |
dudmuck | 0:aad43948c45c | 79 | uint32_t x = 1000000000L; |
dudmuck | 0:aad43948c45c | 80 | int_fast8_t digit; |
dudmuck | 0:aad43948c45c | 81 | size_t pos = 0; |
dudmuck | 0:aad43948c45c | 82 | |
dudmuck | 0:aad43948c45c | 83 | if (val == 0) { |
dudmuck | 0:aad43948c45c | 84 | if (pos < len) str[pos++] = '0'; |
dudmuck | 0:aad43948c45c | 85 | } else { |
dudmuck | 0:aad43948c45c | 86 | if (val < 0) { |
dudmuck | 0:aad43948c45c | 87 | val = -val; |
dudmuck | 0:aad43948c45c | 88 | if (pos < len) str[pos++] = '-'; |
dudmuck | 0:aad43948c45c | 89 | } |
dudmuck | 0:aad43948c45c | 90 | |
dudmuck | 0:aad43948c45c | 91 | while ((val / x) == 0) { |
dudmuck | 0:aad43948c45c | 92 | x /= 10; |
dudmuck | 0:aad43948c45c | 93 | } |
dudmuck | 0:aad43948c45c | 94 | |
dudmuck | 0:aad43948c45c | 95 | do { |
dudmuck | 0:aad43948c45c | 96 | digit = (uint8_t) (val / x); |
dudmuck | 0:aad43948c45c | 97 | if (pos < len) str[pos++] = digit + '0'; |
dudmuck | 0:aad43948c45c | 98 | val -= digit * x; |
dudmuck | 0:aad43948c45c | 99 | x /= 10; |
dudmuck | 0:aad43948c45c | 100 | } while (x && (pos < len)); |
dudmuck | 0:aad43948c45c | 101 | } |
dudmuck | 0:aad43948c45c | 102 | |
dudmuck | 0:aad43948c45c | 103 | if (pos < len) str[pos] = 0; |
dudmuck | 0:aad43948c45c | 104 | return pos; |
dudmuck | 0:aad43948c45c | 105 | } |
dudmuck | 0:aad43948c45c | 106 | |
dudmuck | 0:aad43948c45c | 107 | /** |
dudmuck | 0:aad43948c45c | 108 | * Converts double value to string |
dudmuck | 0:aad43948c45c | 109 | * @param val double value |
dudmuck | 0:aad43948c45c | 110 | * @param str converted textual representation |
dudmuck | 0:aad43948c45c | 111 | * @param len string buffer length |
dudmuck | 0:aad43948c45c | 112 | * @return number of bytes written to str (without '\0') |
dudmuck | 0:aad43948c45c | 113 | */ |
dudmuck | 0:aad43948c45c | 114 | size_t doubleToStr(double val, char * str, size_t len) { |
dudmuck | 0:aad43948c45c | 115 | return snprintf(str, len, "%lg", val); |
dudmuck | 0:aad43948c45c | 116 | } |
dudmuck | 0:aad43948c45c | 117 | |
dudmuck | 0:aad43948c45c | 118 | /** |
dudmuck | 0:aad43948c45c | 119 | * Converts string to signed 32bit integer representation |
dudmuck | 0:aad43948c45c | 120 | * @param str string value |
dudmuck | 0:aad43948c45c | 121 | * @param val 32bit integer result |
dudmuck | 0:aad43948c45c | 122 | * @return number of bytes used in string |
dudmuck | 0:aad43948c45c | 123 | */ |
dudmuck | 0:aad43948c45c | 124 | size_t strToLong(const char * str, int32_t * val) { |
dudmuck | 0:aad43948c45c | 125 | char * endptr; |
dudmuck | 0:aad43948c45c | 126 | *val = strtol(str, &endptr, 0); |
dudmuck | 0:aad43948c45c | 127 | return endptr - str; |
dudmuck | 0:aad43948c45c | 128 | } |
dudmuck | 0:aad43948c45c | 129 | |
dudmuck | 0:aad43948c45c | 130 | /** |
dudmuck | 0:aad43948c45c | 131 | * Converts string to double representation |
dudmuck | 0:aad43948c45c | 132 | * @param str string value |
dudmuck | 0:aad43948c45c | 133 | * @param val double result |
dudmuck | 0:aad43948c45c | 134 | * @return number of bytes used in string |
dudmuck | 0:aad43948c45c | 135 | */ |
dudmuck | 0:aad43948c45c | 136 | size_t strToDouble(const char * str, double * val) { |
dudmuck | 0:aad43948c45c | 137 | char * endptr; |
dudmuck | 0:aad43948c45c | 138 | *val = strtod(str, &endptr); |
dudmuck | 0:aad43948c45c | 139 | return endptr - str; |
dudmuck | 0:aad43948c45c | 140 | } |
dudmuck | 0:aad43948c45c | 141 | |
dudmuck | 0:aad43948c45c | 142 | /** |
dudmuck | 0:aad43948c45c | 143 | * Compare two strings with exact length |
dudmuck | 0:aad43948c45c | 144 | * @param str1 |
dudmuck | 0:aad43948c45c | 145 | * @param len1 |
dudmuck | 0:aad43948c45c | 146 | * @param str2 |
dudmuck | 0:aad43948c45c | 147 | * @param len2 |
dudmuck | 0:aad43948c45c | 148 | * @return TRUE if len1==len2 and "len" characters of both strings are equal |
dudmuck | 0:aad43948c45c | 149 | */ |
dudmuck | 0:aad43948c45c | 150 | scpi_bool_t compareStr(const char * str1, size_t len1, const char * str2, size_t len2) { |
dudmuck | 0:aad43948c45c | 151 | if (len1 != len2) { |
dudmuck | 0:aad43948c45c | 152 | return FALSE; |
dudmuck | 0:aad43948c45c | 153 | } |
dudmuck | 0:aad43948c45c | 154 | |
dudmuck | 0:aad43948c45c | 155 | if (SCPI_strncasecmp(str1, str2, len2) == 0) { |
dudmuck | 0:aad43948c45c | 156 | return TRUE; |
dudmuck | 0:aad43948c45c | 157 | } |
dudmuck | 0:aad43948c45c | 158 | |
dudmuck | 0:aad43948c45c | 159 | return FALSE; |
dudmuck | 0:aad43948c45c | 160 | } |
dudmuck | 0:aad43948c45c | 161 | |
dudmuck | 0:aad43948c45c | 162 | /** |
dudmuck | 0:aad43948c45c | 163 | * Compare two strings, one be longer but may contains only numbers in that section |
dudmuck | 0:aad43948c45c | 164 | * @param str1 |
dudmuck | 0:aad43948c45c | 165 | * @param len1 |
dudmuck | 0:aad43948c45c | 166 | * @param str2 |
dudmuck | 0:aad43948c45c | 167 | * @param len2 |
dudmuck | 0:aad43948c45c | 168 | * @return TRUE if strings match |
dudmuck | 0:aad43948c45c | 169 | */ |
dudmuck | 0:aad43948c45c | 170 | scpi_bool_t compareStrAndNum(const char * str1, size_t len1, const char * str2, size_t len2) { |
dudmuck | 0:aad43948c45c | 171 | scpi_bool_t result = FALSE; |
dudmuck | 0:aad43948c45c | 172 | size_t i; |
dudmuck | 0:aad43948c45c | 173 | |
dudmuck | 0:aad43948c45c | 174 | if (len2 < len1) { |
dudmuck | 0:aad43948c45c | 175 | return FALSE; |
dudmuck | 0:aad43948c45c | 176 | } |
dudmuck | 0:aad43948c45c | 177 | |
dudmuck | 0:aad43948c45c | 178 | if (SCPI_strncasecmp(str1, str2, len1) == 0) { |
dudmuck | 0:aad43948c45c | 179 | result = TRUE; |
dudmuck | 0:aad43948c45c | 180 | } |
dudmuck | 0:aad43948c45c | 181 | |
dudmuck | 0:aad43948c45c | 182 | for (i = len1; i<len2; i++) { |
dudmuck | 0:aad43948c45c | 183 | if (!isdigit((int) str2[i])) { |
dudmuck | 0:aad43948c45c | 184 | result = FALSE; |
dudmuck | 0:aad43948c45c | 185 | break; |
dudmuck | 0:aad43948c45c | 186 | } |
dudmuck | 0:aad43948c45c | 187 | } |
dudmuck | 0:aad43948c45c | 188 | |
dudmuck | 0:aad43948c45c | 189 | return result; |
dudmuck | 0:aad43948c45c | 190 | } |
dudmuck | 0:aad43948c45c | 191 | |
dudmuck | 0:aad43948c45c | 192 | enum _locate_text_states { |
dudmuck | 0:aad43948c45c | 193 | STATE_FIRST_WHITESPACE, |
dudmuck | 0:aad43948c45c | 194 | STATE_TEXT_QUOTED, |
dudmuck | 0:aad43948c45c | 195 | STATE_TEXT, |
dudmuck | 0:aad43948c45c | 196 | STATE_LAST_WHITESPACE, |
dudmuck | 0:aad43948c45c | 197 | STATE_COMMA, |
dudmuck | 0:aad43948c45c | 198 | STATE_ERROR |
dudmuck | 0:aad43948c45c | 199 | }; |
dudmuck | 0:aad43948c45c | 200 | typedef enum _locate_text_states locate_text_states; |
dudmuck | 0:aad43948c45c | 201 | |
dudmuck | 0:aad43948c45c | 202 | struct _locate_text_nfa { |
dudmuck | 0:aad43948c45c | 203 | locate_text_states state; |
dudmuck | 0:aad43948c45c | 204 | int32_t startIdx; |
dudmuck | 0:aad43948c45c | 205 | int32_t stopIdx; |
dudmuck | 0:aad43948c45c | 206 | size_t i; |
dudmuck | 0:aad43948c45c | 207 | }; |
dudmuck | 0:aad43948c45c | 208 | typedef struct _locate_text_nfa locate_text_nfa; |
dudmuck | 0:aad43948c45c | 209 | |
dudmuck | 0:aad43948c45c | 210 | /** |
dudmuck | 0:aad43948c45c | 211 | * Test locate text state, if it is correct final state |
dudmuck | 0:aad43948c45c | 212 | */ |
dudmuck | 0:aad43948c45c | 213 | static scpi_bool_t isFinalState(locate_text_states state) { |
dudmuck | 0:aad43948c45c | 214 | return ( |
dudmuck | 0:aad43948c45c | 215 | ((state) == STATE_COMMA) |
dudmuck | 0:aad43948c45c | 216 | || ((state) == STATE_LAST_WHITESPACE) |
dudmuck | 0:aad43948c45c | 217 | || ((state) == STATE_TEXT) || |
dudmuck | 0:aad43948c45c | 218 | ((state) == STATE_FIRST_WHITESPACE) |
dudmuck | 0:aad43948c45c | 219 | ); |
dudmuck | 0:aad43948c45c | 220 | } |
dudmuck | 0:aad43948c45c | 221 | |
dudmuck | 0:aad43948c45c | 222 | /** |
dudmuck | 0:aad43948c45c | 223 | * Perform locateText automaton to search string pattern |
dudmuck | 0:aad43948c45c | 224 | * @param nfa stores automaton state |
dudmuck | 0:aad43948c45c | 225 | * @param c current char processed |
dudmuck | 0:aad43948c45c | 226 | */ |
dudmuck | 0:aad43948c45c | 227 | static scpi_bool_t locateTextAutomaton(locate_text_nfa * nfa, unsigned char c) { |
dudmuck | 0:aad43948c45c | 228 | switch(nfa->state) { |
dudmuck | 0:aad43948c45c | 229 | /* first state locating only white spaces */ |
dudmuck | 0:aad43948c45c | 230 | case STATE_FIRST_WHITESPACE: |
dudmuck | 0:aad43948c45c | 231 | if(isspace(c)) { |
dudmuck | 0:aad43948c45c | 232 | nfa->startIdx = nfa->stopIdx = nfa->i + 1; |
dudmuck | 0:aad43948c45c | 233 | } else if (c == ',') { |
dudmuck | 0:aad43948c45c | 234 | nfa->state = STATE_COMMA; |
dudmuck | 0:aad43948c45c | 235 | } else if (c == '"') { |
dudmuck | 0:aad43948c45c | 236 | nfa->startIdx = nfa->i + 1; |
dudmuck | 0:aad43948c45c | 237 | nfa->state = STATE_TEXT_QUOTED; |
dudmuck | 0:aad43948c45c | 238 | } else { |
dudmuck | 0:aad43948c45c | 239 | nfa->startIdx = nfa->i; |
dudmuck | 0:aad43948c45c | 240 | nfa->stopIdx = nfa->i + 1; |
dudmuck | 0:aad43948c45c | 241 | nfa->state = STATE_TEXT; |
dudmuck | 0:aad43948c45c | 242 | } |
dudmuck | 0:aad43948c45c | 243 | break; |
dudmuck | 0:aad43948c45c | 244 | /* state locating any text inside "" */ |
dudmuck | 0:aad43948c45c | 245 | case STATE_TEXT_QUOTED: |
dudmuck | 0:aad43948c45c | 246 | if(c == '"') { |
dudmuck | 0:aad43948c45c | 247 | nfa->state = STATE_LAST_WHITESPACE; |
dudmuck | 0:aad43948c45c | 248 | nfa->stopIdx = nfa->i; |
dudmuck | 0:aad43948c45c | 249 | } |
dudmuck | 0:aad43948c45c | 250 | break; |
dudmuck | 0:aad43948c45c | 251 | /* locate text ignoring quotes */ |
dudmuck | 0:aad43948c45c | 252 | case STATE_TEXT: |
dudmuck | 0:aad43948c45c | 253 | if (c == ',') { |
dudmuck | 0:aad43948c45c | 254 | nfa->state = STATE_COMMA; |
dudmuck | 0:aad43948c45c | 255 | } else if (!isspace(c)) { |
dudmuck | 0:aad43948c45c | 256 | nfa->stopIdx = nfa->i + 1; |
dudmuck | 0:aad43948c45c | 257 | } |
dudmuck | 0:aad43948c45c | 258 | break; |
dudmuck | 0:aad43948c45c | 259 | /* locating text after last quote */ |
dudmuck | 0:aad43948c45c | 260 | case STATE_LAST_WHITESPACE: |
dudmuck | 0:aad43948c45c | 261 | if (c == ',') { |
dudmuck | 0:aad43948c45c | 262 | nfa->state = STATE_COMMA; |
dudmuck | 0:aad43948c45c | 263 | } else if (!isspace(c)) { |
dudmuck | 0:aad43948c45c | 264 | nfa->state = STATE_ERROR; |
dudmuck | 0:aad43948c45c | 265 | } |
dudmuck | 0:aad43948c45c | 266 | break; |
dudmuck | 0:aad43948c45c | 267 | |
dudmuck | 0:aad43948c45c | 268 | default: |
dudmuck | 0:aad43948c45c | 269 | break; |
dudmuck | 0:aad43948c45c | 270 | } |
dudmuck | 0:aad43948c45c | 271 | |
dudmuck | 0:aad43948c45c | 272 | /* if it is terminating state, break from for loop */ |
dudmuck | 0:aad43948c45c | 273 | if ((nfa->state == STATE_COMMA) || (nfa->state == STATE_ERROR)) { |
dudmuck | 0:aad43948c45c | 274 | return FALSE; |
dudmuck | 0:aad43948c45c | 275 | } else { |
dudmuck | 0:aad43948c45c | 276 | return TRUE; |
dudmuck | 0:aad43948c45c | 277 | } |
dudmuck | 0:aad43948c45c | 278 | } |
dudmuck | 0:aad43948c45c | 279 | |
dudmuck | 0:aad43948c45c | 280 | /** |
dudmuck | 0:aad43948c45c | 281 | * Locate text in string. Text is separated by two "" |
dudmuck | 0:aad43948c45c | 282 | * example: "text", next parameter |
dudmuck | 0:aad43948c45c | 283 | * regexp: ^[ \t\r\n]*"([^"]*)"[ \t\r\n]*,? |
dudmuck | 0:aad43948c45c | 284 | * regexp: ^[ \t\r\n]*([^,]*)[ \t\r\n]*,? |
dudmuck | 0:aad43948c45c | 285 | * @param str1 string to be searched |
dudmuck | 0:aad43948c45c | 286 | * @param len1 length of string |
dudmuck | 0:aad43948c45c | 287 | * @param str2 result |
dudmuck | 0:aad43948c45c | 288 | * @param len2 length of result |
dudmuck | 0:aad43948c45c | 289 | * @return string str1 contains text and str2 was set |
dudmuck | 0:aad43948c45c | 290 | */ |
dudmuck | 0:aad43948c45c | 291 | scpi_bool_t locateText(const char * str1, size_t len1, const char ** str2, size_t * len2) { |
dudmuck | 0:aad43948c45c | 292 | locate_text_nfa nfa; |
dudmuck | 0:aad43948c45c | 293 | nfa.state = STATE_FIRST_WHITESPACE; |
dudmuck | 0:aad43948c45c | 294 | nfa.startIdx = 0; |
dudmuck | 0:aad43948c45c | 295 | nfa.stopIdx = 0; |
dudmuck | 0:aad43948c45c | 296 | |
dudmuck | 0:aad43948c45c | 297 | for (nfa.i = 0; nfa.i < len1; nfa.i++) { |
dudmuck | 0:aad43948c45c | 298 | if(FALSE == locateTextAutomaton(&nfa, str1[nfa.i])) { |
dudmuck | 0:aad43948c45c | 299 | break; |
dudmuck | 0:aad43948c45c | 300 | } |
dudmuck | 0:aad43948c45c | 301 | } |
dudmuck | 0:aad43948c45c | 302 | |
dudmuck | 0:aad43948c45c | 303 | if (isFinalState(nfa.state)) { |
dudmuck | 0:aad43948c45c | 304 | |
dudmuck | 0:aad43948c45c | 305 | if (str2) { |
dudmuck | 0:aad43948c45c | 306 | *str2 = &str1[nfa.startIdx]; |
dudmuck | 0:aad43948c45c | 307 | } |
dudmuck | 0:aad43948c45c | 308 | |
dudmuck | 0:aad43948c45c | 309 | if (len2) { |
dudmuck | 0:aad43948c45c | 310 | *len2 = nfa.stopIdx - nfa.startIdx; |
dudmuck | 0:aad43948c45c | 311 | } |
dudmuck | 0:aad43948c45c | 312 | return TRUE; |
dudmuck | 0:aad43948c45c | 313 | } |
dudmuck | 0:aad43948c45c | 314 | return FALSE; |
dudmuck | 0:aad43948c45c | 315 | } |
dudmuck | 0:aad43948c45c | 316 | |
dudmuck | 0:aad43948c45c | 317 | /** |
dudmuck | 0:aad43948c45c | 318 | * Perform locateStr automaton to search string pattern |
dudmuck | 0:aad43948c45c | 319 | * @param nfa stores automaton state |
dudmuck | 0:aad43948c45c | 320 | * @param c current char processed |
dudmuck | 0:aad43948c45c | 321 | */ |
dudmuck | 0:aad43948c45c | 322 | static scpi_bool_t locateStrAutomaton(locate_text_nfa * nfa, unsigned char c) { |
dudmuck | 0:aad43948c45c | 323 | switch(nfa->state) { |
dudmuck | 0:aad43948c45c | 324 | /* first state locating only white spaces */ |
dudmuck | 0:aad43948c45c | 325 | case STATE_FIRST_WHITESPACE: |
dudmuck | 0:aad43948c45c | 326 | if(isspace(c)) { |
dudmuck | 0:aad43948c45c | 327 | nfa->startIdx = nfa->stopIdx = nfa->i + 1; |
dudmuck | 0:aad43948c45c | 328 | } else if (c == ',') { |
dudmuck | 0:aad43948c45c | 329 | nfa->state = STATE_COMMA; |
dudmuck | 0:aad43948c45c | 330 | } else { |
dudmuck | 0:aad43948c45c | 331 | nfa->startIdx = nfa->i; |
dudmuck | 0:aad43948c45c | 332 | nfa->stopIdx = nfa->i + 1; |
dudmuck | 0:aad43948c45c | 333 | nfa->state = STATE_TEXT; |
dudmuck | 0:aad43948c45c | 334 | } |
dudmuck | 0:aad43948c45c | 335 | break; |
dudmuck | 0:aad43948c45c | 336 | /* locate text ignoring quotes */ |
dudmuck | 0:aad43948c45c | 337 | case STATE_TEXT: |
dudmuck | 0:aad43948c45c | 338 | if (c == ',') { |
dudmuck | 0:aad43948c45c | 339 | nfa->state = STATE_COMMA; |
dudmuck | 0:aad43948c45c | 340 | } else if (!isspace(c)) { |
dudmuck | 0:aad43948c45c | 341 | nfa->stopIdx = nfa->i + 1; |
dudmuck | 0:aad43948c45c | 342 | } |
dudmuck | 0:aad43948c45c | 343 | break; |
dudmuck | 0:aad43948c45c | 344 | |
dudmuck | 0:aad43948c45c | 345 | default: |
dudmuck | 0:aad43948c45c | 346 | break; |
dudmuck | 0:aad43948c45c | 347 | } |
dudmuck | 0:aad43948c45c | 348 | |
dudmuck | 0:aad43948c45c | 349 | /* if it is terminating state, break from for loop */ |
dudmuck | 0:aad43948c45c | 350 | if ((nfa->state == STATE_COMMA) || (nfa->state == STATE_ERROR)) { |
dudmuck | 0:aad43948c45c | 351 | return FALSE; |
dudmuck | 0:aad43948c45c | 352 | } else { |
dudmuck | 0:aad43948c45c | 353 | return TRUE; |
dudmuck | 0:aad43948c45c | 354 | } |
dudmuck | 0:aad43948c45c | 355 | } |
dudmuck | 0:aad43948c45c | 356 | |
dudmuck | 0:aad43948c45c | 357 | /** |
dudmuck | 0:aad43948c45c | 358 | * Locate string in string. |
dudmuck | 0:aad43948c45c | 359 | * regexp: ^[ \t\r\n]*([^,]*)[ \t\r\n]*,? |
dudmuck | 0:aad43948c45c | 360 | * @param str1 string to be searched |
dudmuck | 0:aad43948c45c | 361 | * @param len1 length of string |
dudmuck | 0:aad43948c45c | 362 | * @param str2 result |
dudmuck | 0:aad43948c45c | 363 | * @param len2 length of result |
dudmuck | 0:aad43948c45c | 364 | * @return string str1 contains text and str2 was set |
dudmuck | 0:aad43948c45c | 365 | */ |
dudmuck | 0:aad43948c45c | 366 | scpi_bool_t locateStr(const char * str1, size_t len1, const char ** str2, size_t * len2) { |
dudmuck | 0:aad43948c45c | 367 | locate_text_nfa nfa; |
dudmuck | 0:aad43948c45c | 368 | nfa.state = STATE_FIRST_WHITESPACE; |
dudmuck | 0:aad43948c45c | 369 | nfa.startIdx = 0; |
dudmuck | 0:aad43948c45c | 370 | nfa.stopIdx = 0; |
dudmuck | 0:aad43948c45c | 371 | |
dudmuck | 0:aad43948c45c | 372 | |
dudmuck | 0:aad43948c45c | 373 | for (nfa.i = 0; nfa.i < len1; nfa.i++) { |
dudmuck | 0:aad43948c45c | 374 | if(FALSE == locateStrAutomaton(&nfa, str1[nfa.i])) { |
dudmuck | 0:aad43948c45c | 375 | break; |
dudmuck | 0:aad43948c45c | 376 | } |
dudmuck | 0:aad43948c45c | 377 | } |
dudmuck | 0:aad43948c45c | 378 | |
dudmuck | 0:aad43948c45c | 379 | if (isFinalState(nfa.state)) { |
dudmuck | 0:aad43948c45c | 380 | |
dudmuck | 0:aad43948c45c | 381 | if (str2) { |
dudmuck | 0:aad43948c45c | 382 | *str2 = &str1[nfa.startIdx]; |
dudmuck | 0:aad43948c45c | 383 | } |
dudmuck | 0:aad43948c45c | 384 | |
dudmuck | 0:aad43948c45c | 385 | if (len2) { |
dudmuck | 0:aad43948c45c | 386 | *len2 = nfa.stopIdx - nfa.startIdx; |
dudmuck | 0:aad43948c45c | 387 | } |
dudmuck | 0:aad43948c45c | 388 | return TRUE; |
dudmuck | 0:aad43948c45c | 389 | } |
dudmuck | 0:aad43948c45c | 390 | return FALSE; |
dudmuck | 0:aad43948c45c | 391 | } |
dudmuck | 0:aad43948c45c | 392 | |
dudmuck | 0:aad43948c45c | 393 | |
dudmuck | 0:aad43948c45c | 394 | /** |
dudmuck | 0:aad43948c45c | 395 | * Count white spaces from the beggining |
dudmuck | 0:aad43948c45c | 396 | * @param cmd - command |
dudmuck | 0:aad43948c45c | 397 | * @param len - max search length |
dudmuck | 0:aad43948c45c | 398 | * @return number of white spaces |
dudmuck | 0:aad43948c45c | 399 | */ |
dudmuck | 0:aad43948c45c | 400 | size_t skipWhitespace(const char * cmd, size_t len) { |
dudmuck | 0:aad43948c45c | 401 | size_t i; |
dudmuck | 0:aad43948c45c | 402 | for (i = 0; i < len; i++) { |
dudmuck | 0:aad43948c45c | 403 | if (!isspace((unsigned char) cmd[i])) { |
dudmuck | 0:aad43948c45c | 404 | return i; |
dudmuck | 0:aad43948c45c | 405 | } |
dudmuck | 0:aad43948c45c | 406 | } |
dudmuck | 0:aad43948c45c | 407 | return len; |
dudmuck | 0:aad43948c45c | 408 | } |
dudmuck | 0:aad43948c45c | 409 | |
dudmuck | 0:aad43948c45c | 410 | /** |
dudmuck | 0:aad43948c45c | 411 | * Pattern is composed from upper case an lower case letters. This function |
dudmuck | 0:aad43948c45c | 412 | * search the first lowercase letter |
dudmuck | 0:aad43948c45c | 413 | * @param pattern |
dudmuck | 0:aad43948c45c | 414 | * @param len - max search length |
dudmuck | 0:aad43948c45c | 415 | * @return position of separator or len |
dudmuck | 0:aad43948c45c | 416 | */ |
dudmuck | 0:aad43948c45c | 417 | size_t patternSeparatorShortPos(const char * pattern, size_t len) { |
dudmuck | 0:aad43948c45c | 418 | size_t i; |
dudmuck | 0:aad43948c45c | 419 | for (i = 0; (i < len) && pattern[i]; i++) { |
dudmuck | 0:aad43948c45c | 420 | if (islower((unsigned char) pattern[i])) { |
dudmuck | 0:aad43948c45c | 421 | return i; |
dudmuck | 0:aad43948c45c | 422 | } |
dudmuck | 0:aad43948c45c | 423 | } |
dudmuck | 0:aad43948c45c | 424 | return i; |
dudmuck | 0:aad43948c45c | 425 | } |
dudmuck | 0:aad43948c45c | 426 | |
dudmuck | 0:aad43948c45c | 427 | /** |
dudmuck | 0:aad43948c45c | 428 | * Find pattern separator position |
dudmuck | 0:aad43948c45c | 429 | * @param pattern |
dudmuck | 0:aad43948c45c | 430 | * @param len - max search length |
dudmuck | 0:aad43948c45c | 431 | * @return position of separator or len |
dudmuck | 0:aad43948c45c | 432 | */ |
dudmuck | 0:aad43948c45c | 433 | size_t patternSeparatorPos(const char * pattern, size_t len) { |
dudmuck | 0:aad43948c45c | 434 | |
dudmuck | 0:aad43948c45c | 435 | const char * separator = strnpbrk(pattern, len, "?:[]"); |
dudmuck | 0:aad43948c45c | 436 | if (separator == NULL) { |
dudmuck | 0:aad43948c45c | 437 | return len; |
dudmuck | 0:aad43948c45c | 438 | } else { |
dudmuck | 0:aad43948c45c | 439 | return separator - pattern; |
dudmuck | 0:aad43948c45c | 440 | } |
dudmuck | 0:aad43948c45c | 441 | } |
dudmuck | 0:aad43948c45c | 442 | |
dudmuck | 0:aad43948c45c | 443 | /** |
dudmuck | 0:aad43948c45c | 444 | * Find command separator position |
dudmuck | 0:aad43948c45c | 445 | * @param cmd - input command |
dudmuck | 0:aad43948c45c | 446 | * @param len - max search length |
dudmuck | 0:aad43948c45c | 447 | * @return position of separator or len |
dudmuck | 0:aad43948c45c | 448 | */ |
dudmuck | 0:aad43948c45c | 449 | size_t cmdSeparatorPos(const char * cmd, size_t len) { |
dudmuck | 0:aad43948c45c | 450 | const char * separator = strnpbrk(cmd, len, ":?"); |
dudmuck | 0:aad43948c45c | 451 | size_t result; |
dudmuck | 0:aad43948c45c | 452 | if (separator == NULL) { |
dudmuck | 0:aad43948c45c | 453 | result = len; |
dudmuck | 0:aad43948c45c | 454 | } else { |
dudmuck | 0:aad43948c45c | 455 | result = separator - cmd; |
dudmuck | 0:aad43948c45c | 456 | } |
dudmuck | 0:aad43948c45c | 457 | |
dudmuck | 0:aad43948c45c | 458 | return result; |
dudmuck | 0:aad43948c45c | 459 | } |
dudmuck | 0:aad43948c45c | 460 | |
dudmuck | 0:aad43948c45c | 461 | /** |
dudmuck | 0:aad43948c45c | 462 | * Match pattern and str. Pattern is in format UPPERCASElowercase |
dudmuck | 0:aad43948c45c | 463 | * @param pattern |
dudmuck | 0:aad43948c45c | 464 | * @param pattern_len |
dudmuck | 0:aad43948c45c | 465 | * @param str |
dudmuck | 0:aad43948c45c | 466 | * @param str_len |
dudmuck | 0:aad43948c45c | 467 | * @return |
dudmuck | 0:aad43948c45c | 468 | */ |
dudmuck | 0:aad43948c45c | 469 | scpi_bool_t matchPattern(const char * pattern, size_t pattern_len, const char * str, size_t str_len) { |
dudmuck | 0:aad43948c45c | 470 | int pattern_sep_pos_short; |
dudmuck | 0:aad43948c45c | 471 | |
dudmuck | 0:aad43948c45c | 472 | if (pattern[pattern_len - 1] == '#') { |
dudmuck | 0:aad43948c45c | 473 | size_t new_pattern_len = pattern_len - 1; |
dudmuck | 0:aad43948c45c | 474 | |
dudmuck | 0:aad43948c45c | 475 | pattern_sep_pos_short = patternSeparatorShortPos(pattern, new_pattern_len); |
dudmuck | 0:aad43948c45c | 476 | |
dudmuck | 0:aad43948c45c | 477 | return compareStrAndNum(pattern, new_pattern_len, str, str_len) || |
dudmuck | 0:aad43948c45c | 478 | compareStrAndNum(pattern, pattern_sep_pos_short, str, str_len); |
dudmuck | 0:aad43948c45c | 479 | } else { |
dudmuck | 0:aad43948c45c | 480 | |
dudmuck | 0:aad43948c45c | 481 | pattern_sep_pos_short = patternSeparatorShortPos(pattern, pattern_len); |
dudmuck | 0:aad43948c45c | 482 | |
dudmuck | 0:aad43948c45c | 483 | return compareStr(pattern, pattern_len, str, str_len) || |
dudmuck | 0:aad43948c45c | 484 | compareStr(pattern, pattern_sep_pos_short, str, str_len); |
dudmuck | 0:aad43948c45c | 485 | } |
dudmuck | 0:aad43948c45c | 486 | } |
dudmuck | 0:aad43948c45c | 487 | |
dudmuck | 0:aad43948c45c | 488 | /** |
dudmuck | 0:aad43948c45c | 489 | * Compare pattern and command |
dudmuck | 0:aad43948c45c | 490 | * @param pattern eg. [:MEASure]:VOLTage:DC? |
dudmuck | 0:aad43948c45c | 491 | * @param cmd - command |
dudmuck | 0:aad43948c45c | 492 | * @param len - max search length |
dudmuck | 0:aad43948c45c | 493 | * @return TRUE if pattern matches, FALSE otherwise |
dudmuck | 0:aad43948c45c | 494 | */ |
dudmuck | 0:aad43948c45c | 495 | scpi_bool_t matchCommand(const char * pattern, const char * cmd, size_t len) { |
dudmuck | 0:aad43948c45c | 496 | scpi_bool_t result = FALSE; |
dudmuck | 0:aad43948c45c | 497 | int leftFlag = 0; // flag for '[' on left |
dudmuck | 0:aad43948c45c | 498 | int rightFlag = 0; // flag for ']' on right |
dudmuck | 0:aad43948c45c | 499 | int cmd_sep_pos = 0; |
dudmuck | 0:aad43948c45c | 500 | |
dudmuck | 0:aad43948c45c | 501 | const char * pattern_ptr = pattern; |
dudmuck | 0:aad43948c45c | 502 | int pattern_len = strlen(pattern); |
dudmuck | 0:aad43948c45c | 503 | const char * pattern_end = pattern + pattern_len; |
dudmuck | 0:aad43948c45c | 504 | |
dudmuck | 0:aad43948c45c | 505 | const char * cmd_ptr = cmd; |
dudmuck | 0:aad43948c45c | 506 | size_t cmd_len = SCPI_strnlen(cmd, len); |
dudmuck | 0:aad43948c45c | 507 | const char * cmd_end = cmd + cmd_len; |
dudmuck | 0:aad43948c45c | 508 | |
dudmuck | 0:aad43948c45c | 509 | /* now support optional keywords in pattern style, e.g. [:MEASure]:VOLTage:DC? */ |
dudmuck | 0:aad43948c45c | 510 | if (pattern_ptr[0] == '[') { // skip first '[' |
dudmuck | 0:aad43948c45c | 511 | pattern_len--; |
dudmuck | 0:aad43948c45c | 512 | pattern_ptr++; |
dudmuck | 0:aad43948c45c | 513 | leftFlag++; |
dudmuck | 0:aad43948c45c | 514 | } |
dudmuck | 0:aad43948c45c | 515 | if (pattern_ptr[0] == ':') { // skip first ':' |
dudmuck | 0:aad43948c45c | 516 | pattern_len--; |
dudmuck | 0:aad43948c45c | 517 | pattern_ptr++; |
dudmuck | 0:aad43948c45c | 518 | } |
dudmuck | 0:aad43948c45c | 519 | |
dudmuck | 0:aad43948c45c | 520 | if (cmd_ptr[0] == ':') { |
dudmuck | 0:aad43948c45c | 521 | /* handle errornouse ":*IDN?" */ |
dudmuck | 0:aad43948c45c | 522 | if((cmd_len >= 2) && (cmd_ptr[1] != '*')) { |
dudmuck | 0:aad43948c45c | 523 | cmd_len--; |
dudmuck | 0:aad43948c45c | 524 | cmd_ptr++; |
dudmuck | 0:aad43948c45c | 525 | } |
dudmuck | 0:aad43948c45c | 526 | } |
dudmuck | 0:aad43948c45c | 527 | |
dudmuck | 0:aad43948c45c | 528 | while (1) { |
dudmuck | 0:aad43948c45c | 529 | int pattern_sep_pos = patternSeparatorPos(pattern_ptr, pattern_end - pattern_ptr); |
dudmuck | 0:aad43948c45c | 530 | |
dudmuck | 0:aad43948c45c | 531 | if ((leftFlag > 0) && (rightFlag > 0)) { |
dudmuck | 0:aad43948c45c | 532 | leftFlag--; |
dudmuck | 0:aad43948c45c | 533 | rightFlag--; |
dudmuck | 0:aad43948c45c | 534 | } else { |
dudmuck | 0:aad43948c45c | 535 | cmd_sep_pos = cmdSeparatorPos(cmd_ptr, cmd_end - cmd_ptr); |
dudmuck | 0:aad43948c45c | 536 | } |
dudmuck | 0:aad43948c45c | 537 | |
dudmuck | 0:aad43948c45c | 538 | if (matchPattern(pattern_ptr, pattern_sep_pos, cmd_ptr, cmd_sep_pos)) { |
dudmuck | 0:aad43948c45c | 539 | pattern_ptr = pattern_ptr + pattern_sep_pos; |
dudmuck | 0:aad43948c45c | 540 | cmd_ptr = cmd_ptr + cmd_sep_pos; |
dudmuck | 0:aad43948c45c | 541 | result = TRUE; |
dudmuck | 0:aad43948c45c | 542 | |
dudmuck | 0:aad43948c45c | 543 | /* command is complete */ |
dudmuck | 0:aad43948c45c | 544 | if ((pattern_ptr == pattern_end) && (cmd_ptr >= cmd_end)) { |
dudmuck | 0:aad43948c45c | 545 | break; |
dudmuck | 0:aad43948c45c | 546 | } |
dudmuck | 0:aad43948c45c | 547 | |
dudmuck | 0:aad43948c45c | 548 | /* pattern complete, but command not */ |
dudmuck | 0:aad43948c45c | 549 | if ((pattern_ptr == pattern_end) && (cmd_ptr < cmd_end)) { |
dudmuck | 0:aad43948c45c | 550 | result = FALSE; |
dudmuck | 0:aad43948c45c | 551 | break; |
dudmuck | 0:aad43948c45c | 552 | } |
dudmuck | 0:aad43948c45c | 553 | |
dudmuck | 0:aad43948c45c | 554 | /* command complete, but pattern not */ |
dudmuck | 0:aad43948c45c | 555 | if (cmd_ptr >= cmd_end) { |
dudmuck | 0:aad43948c45c | 556 | if (cmd_end == cmd_ptr) { |
dudmuck | 0:aad43948c45c | 557 | if (cmd_ptr[0] == pattern_ptr[pattern_end - pattern_ptr - 1]) { |
dudmuck | 0:aad43948c45c | 558 | break; /* exist optional keyword, command is complete */ |
dudmuck | 0:aad43948c45c | 559 | } |
dudmuck | 0:aad43948c45c | 560 | if (']' == pattern_ptr[pattern_end - pattern_ptr - 1]) { |
dudmuck | 0:aad43948c45c | 561 | break; /* exist optional keyword, command is complete */ |
dudmuck | 0:aad43948c45c | 562 | } |
dudmuck | 0:aad43948c45c | 563 | } |
dudmuck | 0:aad43948c45c | 564 | result = FALSE; |
dudmuck | 0:aad43948c45c | 565 | break; |
dudmuck | 0:aad43948c45c | 566 | } |
dudmuck | 0:aad43948c45c | 567 | |
dudmuck | 0:aad43948c45c | 568 | /* both command and patter contains command separator at this position */ |
dudmuck | 0:aad43948c45c | 569 | if ((pattern_ptr[0] == cmd_ptr[0]) && ((pattern_ptr[0] == ':') || (pattern_ptr[0] == '?'))) { |
dudmuck | 0:aad43948c45c | 570 | pattern_ptr = pattern_ptr + 1; |
dudmuck | 0:aad43948c45c | 571 | cmd_ptr = cmd_ptr + 1; |
dudmuck | 0:aad43948c45c | 572 | } else if ((pattern_ptr[1] == cmd_ptr[0]) |
dudmuck | 0:aad43948c45c | 573 | && (pattern_ptr[0] == '[') |
dudmuck | 0:aad43948c45c | 574 | && (pattern_ptr[1] == ':')) { |
dudmuck | 0:aad43948c45c | 575 | pattern_ptr = pattern_ptr + 2; // for skip '[' in "[:" |
dudmuck | 0:aad43948c45c | 576 | cmd_ptr = cmd_ptr + 1; |
dudmuck | 0:aad43948c45c | 577 | leftFlag++; |
dudmuck | 0:aad43948c45c | 578 | } else if ((pattern_ptr[1] == cmd_ptr[0]) |
dudmuck | 0:aad43948c45c | 579 | && (pattern_ptr[0] == ']') |
dudmuck | 0:aad43948c45c | 580 | && (pattern_ptr[1] == ':')) { |
dudmuck | 0:aad43948c45c | 581 | pattern_ptr = pattern_ptr + 2; // for skip ']' in "]:" |
dudmuck | 0:aad43948c45c | 582 | cmd_ptr = cmd_ptr + 1; |
dudmuck | 0:aad43948c45c | 583 | } else if ((pattern_ptr[2] == cmd_ptr[0]) |
dudmuck | 0:aad43948c45c | 584 | && (pattern_ptr[0] == ']') |
dudmuck | 0:aad43948c45c | 585 | && (pattern_ptr[1] == '[') |
dudmuck | 0:aad43948c45c | 586 | && (pattern_ptr[2] == ':')) { |
dudmuck | 0:aad43948c45c | 587 | pattern_ptr = pattern_ptr + 3; // for skip '][' in "][:" |
dudmuck | 0:aad43948c45c | 588 | cmd_ptr = cmd_ptr + 1; |
dudmuck | 0:aad43948c45c | 589 | leftFlag++; |
dudmuck | 0:aad43948c45c | 590 | } else if (((pattern_ptr[0] == ']') |
dudmuck | 0:aad43948c45c | 591 | || (pattern_ptr[0] == '[')) |
dudmuck | 0:aad43948c45c | 592 | && (*(pattern_end - 1) == '?') // last is '?' |
dudmuck | 0:aad43948c45c | 593 | && (cmd_ptr[0] == '?')) { |
dudmuck | 0:aad43948c45c | 594 | result = TRUE; // exist optional keyword, and they are end with '?' |
dudmuck | 0:aad43948c45c | 595 | break; // command is complete OK |
dudmuck | 0:aad43948c45c | 596 | } else { |
dudmuck | 0:aad43948c45c | 597 | result = FALSE; |
dudmuck | 0:aad43948c45c | 598 | break; |
dudmuck | 0:aad43948c45c | 599 | } |
dudmuck | 0:aad43948c45c | 600 | } else { |
dudmuck | 0:aad43948c45c | 601 | pattern_ptr = pattern_ptr + pattern_sep_pos; |
dudmuck | 0:aad43948c45c | 602 | if ((pattern_ptr[0] == ']') && (pattern_ptr[1] == ':')) { |
dudmuck | 0:aad43948c45c | 603 | pattern_ptr = pattern_ptr + 2; // for skip ']' in "]:" , pattern_ptr continue, while cmd_ptr remain unchanged |
dudmuck | 0:aad43948c45c | 604 | rightFlag++; |
dudmuck | 0:aad43948c45c | 605 | } else if ((pattern_ptr[0] == ']') |
dudmuck | 0:aad43948c45c | 606 | && (pattern_ptr[1] == '[') |
dudmuck | 0:aad43948c45c | 607 | && (pattern_ptr[2] == ':')) { |
dudmuck | 0:aad43948c45c | 608 | pattern_ptr = pattern_ptr + 3; // for skip ']' in "][:" , pattern_ptr continue, while cmd_ptr remain unchanged |
dudmuck | 0:aad43948c45c | 609 | rightFlag++; |
dudmuck | 0:aad43948c45c | 610 | } else { |
dudmuck | 0:aad43948c45c | 611 | result = FALSE; |
dudmuck | 0:aad43948c45c | 612 | break; |
dudmuck | 0:aad43948c45c | 613 | } |
dudmuck | 0:aad43948c45c | 614 | } |
dudmuck | 0:aad43948c45c | 615 | } |
dudmuck | 0:aad43948c45c | 616 | |
dudmuck | 0:aad43948c45c | 617 | return result; |
dudmuck | 0:aad43948c45c | 618 | } |
dudmuck | 0:aad43948c45c | 619 | |
dudmuck | 0:aad43948c45c | 620 | /** |
dudmuck | 0:aad43948c45c | 621 | * Compose command from previsou command anc current command |
dudmuck | 0:aad43948c45c | 622 | * |
dudmuck | 0:aad43948c45c | 623 | * @param ptr_prev pointer to previous command |
dudmuck | 0:aad43948c45c | 624 | * @param len_prev length of previous command |
dudmuck | 0:aad43948c45c | 625 | * @param pptr pointer to pointer of current command |
dudmuck | 0:aad43948c45c | 626 | * @param plen pointer to length of current command |
dudmuck | 0:aad43948c45c | 627 | * |
dudmuck | 0:aad43948c45c | 628 | * ptr_prev and ptr should be in the same memory buffer |
dudmuck | 0:aad43948c45c | 629 | * |
dudmuck | 0:aad43948c45c | 630 | * Function will add part of previous command prior to ptr_prev |
dudmuck | 0:aad43948c45c | 631 | * |
dudmuck | 0:aad43948c45c | 632 | * char * cmd = "meas:volt:dc?;ac?" |
dudmuck | 0:aad43948c45c | 633 | * char * ptr_prev = cmd; |
dudmuck | 0:aad43948c45c | 634 | * size_t len_prev = 13; |
dudmuck | 0:aad43948c45c | 635 | * char * ptr = cmd + 14; |
dudmuck | 0:aad43948c45c | 636 | * size_t len = 3; |
dudmuck | 0:aad43948c45c | 637 | * |
dudmuck | 0:aad43948c45c | 638 | * composeCompoundCommand(ptr_prev, len_prev, &ptr, &len); |
dudmuck | 0:aad43948c45c | 639 | * |
dudmuck | 0:aad43948c45c | 640 | * after calling this |
dudmuck | 0:aad43948c45c | 641 | * |
dudmuck | 0:aad43948c45c | 642 | * |
dudmuck | 0:aad43948c45c | 643 | * |
dudmuck | 0:aad43948c45c | 644 | */ |
dudmuck | 0:aad43948c45c | 645 | scpi_bool_t composeCompoundCommand(char * ptr_prev, size_t len_prev, |
dudmuck | 0:aad43948c45c | 646 | char ** pptr, size_t * plen) { |
dudmuck | 0:aad43948c45c | 647 | char * ptr; |
dudmuck | 0:aad43948c45c | 648 | size_t len; |
dudmuck | 0:aad43948c45c | 649 | size_t i; |
dudmuck | 0:aad43948c45c | 650 | |
dudmuck | 0:aad43948c45c | 651 | /* Invalid input */ |
dudmuck | 0:aad43948c45c | 652 | if (pptr == NULL || plen == NULL) |
dudmuck | 0:aad43948c45c | 653 | return FALSE; |
dudmuck | 0:aad43948c45c | 654 | |
dudmuck | 0:aad43948c45c | 655 | /* no previous command - nothing to do*/ |
dudmuck | 0:aad43948c45c | 656 | if (ptr_prev == NULL || len_prev == 0) |
dudmuck | 0:aad43948c45c | 657 | return TRUE; |
dudmuck | 0:aad43948c45c | 658 | |
dudmuck | 0:aad43948c45c | 659 | ptr = *pptr; |
dudmuck | 0:aad43948c45c | 660 | len = *plen; |
dudmuck | 0:aad43948c45c | 661 | |
dudmuck | 0:aad43948c45c | 662 | /* No current command */ |
dudmuck | 0:aad43948c45c | 663 | if (len == 0 || ptr == NULL) |
dudmuck | 0:aad43948c45c | 664 | return FALSE; |
dudmuck | 0:aad43948c45c | 665 | |
dudmuck | 0:aad43948c45c | 666 | /* Common command or command root - nothing to do */ |
dudmuck | 0:aad43948c45c | 667 | if (ptr[0] == '*' || ptr[0] == ':') |
dudmuck | 0:aad43948c45c | 668 | return TRUE; |
dudmuck | 0:aad43948c45c | 669 | |
dudmuck | 0:aad43948c45c | 670 | /* Previsou command was common command - nothing to do */ |
dudmuck | 0:aad43948c45c | 671 | if (ptr_prev[0] == '*') |
dudmuck | 0:aad43948c45c | 672 | return TRUE; |
dudmuck | 0:aad43948c45c | 673 | |
dudmuck | 0:aad43948c45c | 674 | /* Find last occurence of ':' */ |
dudmuck | 0:aad43948c45c | 675 | for (i = len_prev; i > 0; i--) { |
dudmuck | 0:aad43948c45c | 676 | if (ptr_prev[i-1] == ':') { |
dudmuck | 0:aad43948c45c | 677 | break; |
dudmuck | 0:aad43948c45c | 678 | } |
dudmuck | 0:aad43948c45c | 679 | } |
dudmuck | 0:aad43948c45c | 680 | |
dudmuck | 0:aad43948c45c | 681 | /* Previous command was simple command - nothing to do*/ |
dudmuck | 0:aad43948c45c | 682 | if (i == 0) |
dudmuck | 0:aad43948c45c | 683 | return TRUE; |
dudmuck | 0:aad43948c45c | 684 | |
dudmuck | 0:aad43948c45c | 685 | ptr -= i; |
dudmuck | 0:aad43948c45c | 686 | len += i; |
dudmuck | 0:aad43948c45c | 687 | memmove(ptr, ptr_prev, i); |
dudmuck | 0:aad43948c45c | 688 | *plen = len; |
dudmuck | 0:aad43948c45c | 689 | *pptr = ptr; |
dudmuck | 0:aad43948c45c | 690 | return TRUE; |
dudmuck | 0:aad43948c45c | 691 | } |
dudmuck | 0:aad43948c45c | 692 | |
dudmuck | 0:aad43948c45c | 693 | |
dudmuck | 0:aad43948c45c | 694 | |
dudmuck | 0:aad43948c45c | 695 | #if !HAVE_STRNLEN |
dudmuck | 0:aad43948c45c | 696 | /* use FreeBSD strnlen */ |
dudmuck | 0:aad43948c45c | 697 | |
dudmuck | 0:aad43948c45c | 698 | /*- |
dudmuck | 0:aad43948c45c | 699 | * Copyright (c) 2009 David Schultz <das@FreeBSD.org> |
dudmuck | 0:aad43948c45c | 700 | * All rights reserved. |
dudmuck | 0:aad43948c45c | 701 | */ |
dudmuck | 0:aad43948c45c | 702 | size_t |
dudmuck | 0:aad43948c45c | 703 | BSD_strnlen(const char *s, size_t maxlen) { |
dudmuck | 0:aad43948c45c | 704 | size_t len; |
dudmuck | 0:aad43948c45c | 705 | |
dudmuck | 0:aad43948c45c | 706 | for (len = 0; len < maxlen; len++, s++) { |
dudmuck | 0:aad43948c45c | 707 | if (!*s) |
dudmuck | 0:aad43948c45c | 708 | break; |
dudmuck | 0:aad43948c45c | 709 | } |
dudmuck | 0:aad43948c45c | 710 | return (len); |
dudmuck | 0:aad43948c45c | 711 | } |
dudmuck | 0:aad43948c45c | 712 | #endif |
dudmuck | 0:aad43948c45c | 713 | |
dudmuck | 0:aad43948c45c | 714 | #if !HAVE_STRNCASECMP && !HAVE_STRNICMP |
dudmuck | 0:aad43948c45c | 715 | int OUR_strncasecmp(const char *s1, const char *s2, size_t n) { |
dudmuck | 0:aad43948c45c | 716 | unsigned char c1, c2; |
dudmuck | 0:aad43948c45c | 717 | |
dudmuck | 0:aad43948c45c | 718 | for(; n != 0; n--) { |
dudmuck | 0:aad43948c45c | 719 | c1 = tolower((unsigned char)*s1++); |
dudmuck | 0:aad43948c45c | 720 | c2 = tolower((unsigned char)*s2++); |
dudmuck | 0:aad43948c45c | 721 | if (c1 != c2) { |
dudmuck | 0:aad43948c45c | 722 | return c1 - c2; |
dudmuck | 0:aad43948c45c | 723 | } |
dudmuck | 0:aad43948c45c | 724 | if (c1 = '\0') { |
dudmuck | 0:aad43948c45c | 725 | return 0; |
dudmuck | 0:aad43948c45c | 726 | } |
dudmuck | 0:aad43948c45c | 727 | } |
dudmuck | 0:aad43948c45c | 728 | return 0; |
dudmuck | 0:aad43948c45c | 729 | } |
dudmuck | 0:aad43948c45c | 730 | #endif |
dudmuck | 0:aad43948c45c | 731 |