scpi-parser, adopted from github

Dependents:   scpi_parser_test

Committer:
iesensor
Date:
Fri Nov 14 01:07:59 2014 +0000
Revision:
0:d8aca47812e0
tested on K64F

Who changed what in which revision?

UserRevisionLine numberNew 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