https://github.com/j123b567/scpi-parser

Dependents:   scpi_sx127x scpi_sx127x_firstTest MLX90418_I2C_master

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?

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