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