nancy.liao
2025-04-16 5a5250218db5ecf87ff03106b7575419865d07ba
libscpi/src/utils.c
@@ -1,30 +1,29 @@
/*-
 * Copyright (c) 2013 Jan Breuer
 *                    Richard.hmm
 * Copyright (c) 2012 Jan Breuer
 * BSD 2-Clause License
 *
 * All Rights Reserved
 * Copyright (c) 2012-2018, Jan Breuer, Richard.hmm
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * modification, are permitted provided that the following conditions are met:
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
/**
@@ -108,13 +107,13 @@
                break;
        }
        // add sign for numbers in base 10
        /* add sign for numbers in base 10 */
        if (sign && ((int32_t) val < 0) && (base == 10)) {
            uval = -val;
            ADD_CHAR('-');
        }
        // remove leading zeros
        /* remove leading zeros */
        while ((uval / x) == 0) {
            x /= base;
        }
@@ -194,13 +193,13 @@
                break;
        }
        // add sign for numbers in base 10
        /* add sign for numbers in base 10 */
        if (sign && ((int64_t) val < 0) && (base == 10)) {
            uval = -val;
            ADD_CHAR('-');
        }
        // remove leading zeros
        /* remove leading zeros */
        while ((uval / x) == 0) {
            x /= base;
        }
@@ -249,7 +248,8 @@
 * @return number of bytes written to str (without '\0')
 */
size_t SCPI_FloatToStr(float val, char * str, size_t len) {
    return SCPIDEFINE_floatToStr(val, str, len);
    SCPIDEFINE_floatToStr(val, str, len);
    return strlen(str);
}
/**
@@ -260,7 +260,8 @@
 * @return number of bytes written to str (without '\0')
 */
size_t SCPI_DoubleToStr(double val, char * str, size_t len) {
    return SCPIDEFINE_doubleToStr(val, str, len);
    SCPIDEFINE_doubleToStr(val, str, len);
    return strlen(str);
}
/**
@@ -295,7 +296,7 @@
 */
size_t strBaseToInt64(const char * str, int64_t * val, int8_t base) {
    char * endptr;
    *val = strtoll(str, &endptr, base);
    *val = SCPIDEFINE_strtoll(str, &endptr, base);
    return endptr - str;
}
@@ -307,7 +308,7 @@
 */
size_t strBaseToUInt64(const char * str, uint64_t * val, int8_t base) {
    char * endptr;
    *val = strtoull(str, &endptr, base);
    *val = SCPIDEFINE_strtoull(str, &endptr, base);
    return endptr - str;
}
@@ -319,7 +320,7 @@
 */
size_t strToFloat(const char * str, float * val) {
    char * endptr;
    *val = strtof(str, &endptr);
    *val = SCPIDEFINE_strtof(str, &endptr);
    return endptr - str;
}
@@ -376,7 +377,7 @@
        if (num) {
            if (len1 == len2) {
                //*num = 1;
                /* *num = 1; */
            } else {
                int32_t tmpNum;
                i = len1 + strBaseToInt32(str2 + len1, &tmpNum, 10);
@@ -528,11 +529,11 @@
    }
    /* now support optional keywords in pattern style, e.g. [:MEASure]:VOLTage:DC? */
    if (pattern_ptr[0] == '[') { // skip first '['
    if (pattern_ptr[0] == '[') { /* skip first '[' */
        SKIP_PATTERN(1);
        brackets++;
    }
    if (pattern_ptr[0] == ':') { // skip first ':'
    if (pattern_ptr[0] == ':') { /* skip first ':' */
        SKIP_PATTERN(1);
    }
@@ -555,7 +556,7 @@
        if ((pattern_sep_pos > 0) && pattern_ptr[pattern_sep_pos - 1] == '#') {
            if (numbers && (numbers_idx < numbers_len)) {
                number_ptr = numbers + numbers_idx;
                *number_ptr = default_value; // default value
                *number_ptr = default_value; /* default value */
            } else {
                number_ptr = NULL;
            }
@@ -582,7 +583,7 @@
            /* command complete, but pattern not */
            if (cmd_len == 0) {
                // verify all subsequent pattern parts are also optional
                /* verify all subsequent pattern parts are also optional */
                while (pattern_len) {
                    pattern_sep_pos = patternSeparatorPos(pattern_ptr, pattern_len);
                    switch (pattern_ptr[pattern_sep_pos]) {
@@ -620,14 +621,14 @@
                    && (pattern_ptr[1] == cmd_ptr[0])
                    && (pattern_ptr[0] == '[')
                    && (pattern_ptr[1] == ':')) {
                SKIP_PATTERN(2); // for skip '[' in "[:"
                SKIP_PATTERN(2); /* for skip '[' in "[:" */
                SKIP_CMD(1);
                brackets++;
            } else if ((pattern_len > 1)
                    && (pattern_ptr[1] == cmd_ptr[0])
                    && (pattern_ptr[0] == ']')
                    && (pattern_ptr[1] == ':')) {
                SKIP_PATTERN(2); // for skip ']' in "]:"
                SKIP_PATTERN(2); /* for skip ']' in "]:" */
                SKIP_CMD(1);
                brackets--;
            } else if ((pattern_len > 2)
@@ -635,10 +636,10 @@
                    && (pattern_ptr[0] == ']')
                    && (pattern_ptr[1] == '[')
                    && (pattern_ptr[2] == ':')) {
                SKIP_PATTERN(3); // for skip '][' in "][:"
                SKIP_PATTERN(3); /* for skip '][' in "][:" */
                SKIP_CMD(1);
                //brackets++;
                //brackets--;
                /* brackets++; */
                /* brackets--; */
            } else {
                result = FALSE;
                break;
@@ -646,14 +647,14 @@
        } else {
            SKIP_PATTERN(pattern_sep_pos);
            if ((pattern_ptr[0] == ']') && (pattern_ptr[1] == ':')) {
                SKIP_PATTERN(2); // for skip ']' in "]:" , pattern_ptr continue, while cmd_ptr remain unchanged
                SKIP_PATTERN(2); /* for skip ']' in "]:" , pattern_ptr continue, while cmd_ptr remain unchanged */
                brackets--;
            } else if ((pattern_len > 2) && (pattern_ptr[0] == ']')
                    && (pattern_ptr[1] == '[')
                    && (pattern_ptr[2] == ':')) {
                SKIP_PATTERN(3); // for skip ']' in "][:" , pattern_ptr continue, while cmd_ptr remain unchanged
                //brackets++;
                //brackets--;
                SKIP_PATTERN(3); /* for skip ']' in "][:" , pattern_ptr continue, while cmd_ptr remain unchanged */
                /* brackets++; */
                /* brackets--; */
            } else {
                result = FALSE;
                break;
@@ -674,6 +675,8 @@
 *
 * prev and current should be in the same memory buffer
 */
 //组合复合SCPI命令
scpi_bool_t composeCompoundCommand(const scpi_token_t * prev, scpi_token_t * current) {
    size_t i;
@@ -686,6 +689,7 @@
        return TRUE;
    /* Common command or command root - nothing to do */
    // 当前命令是公共命令(*)或根命令(:)
    if (current->ptr[0] == '*' || current->ptr[0] == ':')
        return TRUE;
@@ -706,6 +710,7 @@
    current->ptr -= i;
    current->len += i;
    //复合命令组合
    memmove(current->ptr, prev->ptr, i);
    return TRUE;
}
@@ -750,6 +755,20 @@
}
#endif
#if USE_MEMORY_ALLOCATION_FREE && !HAVE_STRNDUP
char *OUR_strndup(const char *s, size_t n) {
    size_t len = SCPIDEFINE_strnlen(s, n);
    //msvc下需要强转
    char * result =(char*) malloc(len + 1);
    if (!result) {
        return NULL;
    }
    memcpy(result, s, len);
    result[len] = '\0';
    return result;
}
#endif
#if USE_DEVICE_DEPENDENT_ERROR_INFORMATION && !USE_MEMORY_ALLOCATION_FREE
/**
@@ -788,7 +807,7 @@
        return NULL;
    }
    size_t len = SCPIDEFINE_strnlen(s, n) + 1; // additional '\0' at end
    size_t len = SCPIDEFINE_strnlen(s, n) + 1; /* additional '\0' at end */
    if (len > heap->count) {
        return NULL;
    }
@@ -808,7 +827,7 @@
    heap->wr += len;
    heap->count -= len;
    // ensure '\0' a the end
    /* ensure '\0' a the end */
    if (heap->wr > 0) {
        heap->data[heap->wr - 1] = '\0';
    } else {
@@ -889,34 +908,36 @@
#endif
// Floating point to string conversion routines
//
// Copyright (C) 2002 Michael Ringgaard. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.
// 3. Neither the name of the project nor the names of its contributors
//    may be used to endorse or promote products derived from this software
//    without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
/*
 * Floating point to string conversion routines
 *
 * Copyright (C) 2002 Michael Ringgaard. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the project nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */
static char *scpi_ecvt(double arg, int ndigits, int *decpt, int *sign, char *buf, size_t bufsize) {
    int r1, r2;
@@ -991,14 +1012,14 @@
char * SCPI_dtostre(double __val, char * __s, size_t __ssize, unsigned char __prec, unsigned char __flags) {
    char buffer[SCPI_DTOSTRE_BUFFER_SIZE];
    int sign = signbit(__val);
    int sign = SCPIDEFINE_signbit(__val);
    char * s = buffer;
    int decpt;
    if (sign) {
        __val = -__val;
        s[0] = '-';
        s++;
    } else if (!isnan(__val)) {
    } else if (!SCPIDEFINE_isnan(__val)) {
        if (SCPI_DTOSTRE_PLUS_SIGN & __flags) {
            s[0] = '+';
            s++;
@@ -1008,13 +1029,14 @@
        }
    }
    if (!isfinite(__val)) {
        if (isnan(__val)) {
    if (!SCPIDEFINE_isfinite(__val)) {
        if (SCPIDEFINE_isnan(__val)) {
            strcpy(s, (__flags & SCPI_DTOSTRE_UPPERCASE) ? "NAN" : "nan");
        } else {
            strcpy(s, (__flags & SCPI_DTOSTRE_UPPERCASE) ? "INF" : "inf");
        }
        strncpy(__s, buffer, __ssize);
        __s[__ssize - 1] = '\0';
        return __s;
    }
@@ -1068,6 +1090,7 @@
    }
    strncpy(__s, buffer, __ssize);
    __s[__ssize - 1] = '\0';
    return __s;
}
@@ -1101,10 +1124,10 @@
 * @return
 */
uint32_t SCPI_Swap32(uint32_t val) {
    return ((val & 0x000000FF) << 24) |
            ((val & 0x0000FF00) << 8) |
            ((val & 0x00FF0000) >> 8) |
            ((val & 0xFF000000) >> 24);
    return ((val & 0x000000FFul) << 24) |
            ((val & 0x0000FF00ul) << 8) |
            ((val & 0x00FF0000ul) >> 8) |
            ((val & 0xFF000000ul) >> 24);
}
/**
@@ -1113,12 +1136,12 @@
 * @return
 */
uint64_t SCPI_Swap64(uint64_t val) {
    return ((val & 0x00000000000000FFul) << 56) |
            ((val & 0x000000000000FF00ul) << 40) |
            ((val & 0x0000000000FF0000ul) << 24) |
            ((val & 0x00000000FF000000ul) << 8) |
            ((val & 0x000000FF00000000ul) >> 8) |
            ((val & 0x0000FF0000000000ul) >> 24) |
            ((val & 0x00FF000000000000ul) >> 40) |
            ((val & 0xFF00000000000000ul) >> 56);
    return ((val & 0x00000000000000FFull) << 56) |
            ((val & 0x000000000000FF00ull) << 40) |
            ((val & 0x0000000000FF0000ull) << 24) |
            ((val & 0x00000000FF000000ull) << 8) |
            ((val & 0x000000FF00000000ull) >> 8) |
            ((val & 0x0000FF0000000000ull) >> 24) |
            ((val & 0x00FF000000000000ull) >> 40) |
            ((val & 0xFF00000000000000ull) >> 56);
}