Jan Breuer
2012-11-27 2df8ee6c6f411e5fa0b774874e759c5e7b045121
Units parsing completition
13个文件已修改
572 ■■■■■ 已修改文件
netbeans/nbproject/Makefile-Debug.mk 40 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
netbeans/nbproject/Makefile-variables.mk 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
netbeans/nbproject/Package-Debug.bash 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
netbeans/nbproject/configurations.xml 28 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
netbeans/tests/test_scpi_utils.c 89 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
scpi/scpi.c 108 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
scpi/scpi.h 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
scpi/scpi_error.c 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
scpi/scpi_units.c 105 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
scpi/scpi_units.h 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
scpi/scpi_utils.c 98 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
scpi/scpi_utils.h 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
test-parser.c 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
netbeans/nbproject/Makefile-Debug.mk
@@ -63,50 +63,50 @@
ASFLAGS=
# Link Libraries and Options
LDLIBSOPTIONS=-lcunit -lcunit
LDLIBSOPTIONS=-lcunit -lcunit -lcunit
# Build Targets
.build-conf: ${BUILD_SUBPROJECTS}
    "${MAKE}"  -f nbproject/Makefile-${CND_CONF}.mk ${TESTDIR}/TestFiles/f2
    "${MAKE}"  -f nbproject/Makefile-${CND_CONF}.mk ${TESTDIR}/TestFiles/f1
${TESTDIR}/TestFiles/f2: ${OBJECTFILES}
${TESTDIR}/TestFiles/f1: ${OBJECTFILES}
    ${MKDIR} -p ${TESTDIR}/TestFiles
    ${LINK.c} -g3 -o ${TESTDIR}/TestFiles/f2 ${OBJECTFILES} ${LDLIBSOPTIONS}
    ${LINK.c} -g3 -o ${TESTDIR}/TestFiles/f1 ${OBJECTFILES} ${LDLIBSOPTIONS}
${OBJECTDIR}/_ext/760632520/scpi_utils.o: nbproject/Makefile-${CND_CONF}.mk ../scpi/scpi_utils.c 
    ${MKDIR} -p ${OBJECTDIR}/_ext/760632520
    ${RM} $@.d
    $(COMPILE.c) -Wall -I. -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/760632520/scpi_utils.o ../scpi/scpi_utils.c
    $(COMPILE.c) -Wall -I. -I. -I. -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/760632520/scpi_utils.o ../scpi/scpi_utils.c
${OBJECTDIR}/_ext/760632520/scpi_ieee488.o: nbproject/Makefile-${CND_CONF}.mk ../scpi/scpi_ieee488.c 
    ${MKDIR} -p ${OBJECTDIR}/_ext/760632520
    ${RM} $@.d
    $(COMPILE.c) -Wall -I. -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/760632520/scpi_ieee488.o ../scpi/scpi_ieee488.c
    $(COMPILE.c) -Wall -I. -I. -I. -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/760632520/scpi_ieee488.o ../scpi/scpi_ieee488.c
${OBJECTDIR}/_ext/760632520/scpi.o: nbproject/Makefile-${CND_CONF}.mk ../scpi/scpi.c 
    ${MKDIR} -p ${OBJECTDIR}/_ext/760632520
    ${RM} $@.d
    $(COMPILE.c) -Wall -I. -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/760632520/scpi.o ../scpi/scpi.c
    $(COMPILE.c) -Wall -I. -I. -I. -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/760632520/scpi.o ../scpi/scpi.c
${OBJECTDIR}/_ext/760632520/scpi_minimal.o: nbproject/Makefile-${CND_CONF}.mk ../scpi/scpi_minimal.c 
    ${MKDIR} -p ${OBJECTDIR}/_ext/760632520
    ${RM} $@.d
    $(COMPILE.c) -Wall -I. -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/760632520/scpi_minimal.o ../scpi/scpi_minimal.c
    $(COMPILE.c) -Wall -I. -I. -I. -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/760632520/scpi_minimal.o ../scpi/scpi_minimal.c
${OBJECTDIR}/_ext/1472/test-parser.o: nbproject/Makefile-${CND_CONF}.mk ../test-parser.c 
    ${MKDIR} -p ${OBJECTDIR}/_ext/1472
    ${RM} $@.d
    $(COMPILE.c) -Wall -I. -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/1472/test-parser.o ../test-parser.c
    $(COMPILE.c) -Wall -I. -I. -I. -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/1472/test-parser.o ../test-parser.c
${OBJECTDIR}/_ext/760632520/scpi_units.o: nbproject/Makefile-${CND_CONF}.mk ../scpi/scpi_units.c 
    ${MKDIR} -p ${OBJECTDIR}/_ext/760632520
    ${RM} $@.d
    $(COMPILE.c) -Wall -I. -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/760632520/scpi_units.o ../scpi/scpi_units.c
    $(COMPILE.c) -Wall -I. -I. -I. -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/760632520/scpi_units.o ../scpi/scpi_units.c
${OBJECTDIR}/_ext/760632520/scpi_error.o: nbproject/Makefile-${CND_CONF}.mk ../scpi/scpi_error.c 
    ${MKDIR} -p ${OBJECTDIR}/_ext/760632520
    ${RM} $@.d
    $(COMPILE.c) -Wall -I. -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/760632520/scpi_error.o ../scpi/scpi_error.c
    $(COMPILE.c) -Wall -I. -I. -I. -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/760632520/scpi_error.o ../scpi/scpi_error.c
# Subprojects
.build-subprojects:
@@ -121,7 +121,7 @@
${TESTDIR}/tests/test_scpi_utils.o: tests/test_scpi_utils.c 
    ${MKDIR} -p ${TESTDIR}/tests
    ${RM} $@.d
    $(COMPILE.c) -Wall -I. -I. -MMD -MP -MF $@.d -o ${TESTDIR}/tests/test_scpi_utils.o tests/test_scpi_utils.c
    $(COMPILE.c) -Wall -I. -I. -I. -I. -MMD -MP -MF $@.d -o ${TESTDIR}/tests/test_scpi_utils.o tests/test_scpi_utils.c
${OBJECTDIR}/_ext/760632520/scpi_utils_nomain.o: ${OBJECTDIR}/_ext/760632520/scpi_utils.o ../scpi/scpi_utils.c 
@@ -132,7 +132,7 @@
       (echo "$$NMOUTPUT" | ${GREP} 'T _main$$'); \
    then  \
        ${RM} $@.d;\
        $(COMPILE.c) -Wall -I. -Dmain=__nomain -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/760632520/scpi_utils_nomain.o ../scpi/scpi_utils.c;\
        $(COMPILE.c) -Wall -I. -I. -I. -Dmain=__nomain -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/760632520/scpi_utils_nomain.o ../scpi/scpi_utils.c;\
    else  \
        ${CP} ${OBJECTDIR}/_ext/760632520/scpi_utils.o ${OBJECTDIR}/_ext/760632520/scpi_utils_nomain.o;\
    fi
@@ -145,7 +145,7 @@
       (echo "$$NMOUTPUT" | ${GREP} 'T _main$$'); \
    then  \
        ${RM} $@.d;\
        $(COMPILE.c) -Wall -I. -Dmain=__nomain -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/760632520/scpi_ieee488_nomain.o ../scpi/scpi_ieee488.c;\
        $(COMPILE.c) -Wall -I. -I. -I. -Dmain=__nomain -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/760632520/scpi_ieee488_nomain.o ../scpi/scpi_ieee488.c;\
    else  \
        ${CP} ${OBJECTDIR}/_ext/760632520/scpi_ieee488.o ${OBJECTDIR}/_ext/760632520/scpi_ieee488_nomain.o;\
    fi
@@ -158,7 +158,7 @@
       (echo "$$NMOUTPUT" | ${GREP} 'T _main$$'); \
    then  \
        ${RM} $@.d;\
        $(COMPILE.c) -Wall -I. -Dmain=__nomain -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/760632520/scpi_nomain.o ../scpi/scpi.c;\
        $(COMPILE.c) -Wall -I. -I. -I. -Dmain=__nomain -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/760632520/scpi_nomain.o ../scpi/scpi.c;\
    else  \
        ${CP} ${OBJECTDIR}/_ext/760632520/scpi.o ${OBJECTDIR}/_ext/760632520/scpi_nomain.o;\
    fi
@@ -171,7 +171,7 @@
       (echo "$$NMOUTPUT" | ${GREP} 'T _main$$'); \
    then  \
        ${RM} $@.d;\
        $(COMPILE.c) -Wall -I. -Dmain=__nomain -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/760632520/scpi_minimal_nomain.o ../scpi/scpi_minimal.c;\
        $(COMPILE.c) -Wall -I. -I. -I. -Dmain=__nomain -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/760632520/scpi_minimal_nomain.o ../scpi/scpi_minimal.c;\
    else  \
        ${CP} ${OBJECTDIR}/_ext/760632520/scpi_minimal.o ${OBJECTDIR}/_ext/760632520/scpi_minimal_nomain.o;\
    fi
@@ -184,7 +184,7 @@
       (echo "$$NMOUTPUT" | ${GREP} 'T _main$$'); \
    then  \
        ${RM} $@.d;\
        $(COMPILE.c) -Wall -I. -Dmain=__nomain -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/1472/test-parser_nomain.o ../test-parser.c;\
        $(COMPILE.c) -Wall -I. -I. -I. -Dmain=__nomain -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/1472/test-parser_nomain.o ../test-parser.c;\
    else  \
        ${CP} ${OBJECTDIR}/_ext/1472/test-parser.o ${OBJECTDIR}/_ext/1472/test-parser_nomain.o;\
    fi
@@ -197,7 +197,7 @@
       (echo "$$NMOUTPUT" | ${GREP} 'T _main$$'); \
    then  \
        ${RM} $@.d;\
        $(COMPILE.c) -Wall -I. -Dmain=__nomain -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/760632520/scpi_units_nomain.o ../scpi/scpi_units.c;\
        $(COMPILE.c) -Wall -I. -I. -I. -Dmain=__nomain -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/760632520/scpi_units_nomain.o ../scpi/scpi_units.c;\
    else  \
        ${CP} ${OBJECTDIR}/_ext/760632520/scpi_units.o ${OBJECTDIR}/_ext/760632520/scpi_units_nomain.o;\
    fi
@@ -210,7 +210,7 @@
       (echo "$$NMOUTPUT" | ${GREP} 'T _main$$'); \
    then  \
        ${RM} $@.d;\
        $(COMPILE.c) -Wall -I. -Dmain=__nomain -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/760632520/scpi_error_nomain.o ../scpi/scpi_error.c;\
        $(COMPILE.c) -Wall -I. -I. -I. -Dmain=__nomain -MMD -MP -MF $@.d -o ${OBJECTDIR}/_ext/760632520/scpi_error_nomain.o ../scpi/scpi_error.c;\
    else  \
        ${CP} ${OBJECTDIR}/_ext/760632520/scpi_error.o ${OBJECTDIR}/_ext/760632520/scpi_error_nomain.o;\
    fi
@@ -227,7 +227,7 @@
# Clean Targets
.clean-conf: ${CLEAN_SUBPROJECTS}
    ${RM} -r ${CND_BUILDDIR}/${CND_CONF}
    ${RM} ${TESTDIR}/TestFiles/f2
    ${RM} ${TESTDIR}/TestFiles/f1
# Subprojects
.clean-subprojects:
netbeans/nbproject/Makefile-variables.mk
@@ -9,8 +9,8 @@
# Debug configuration
CND_PLATFORM_Debug=GNU-Linux-x86
CND_ARTIFACT_DIR_Debug=build/Debug/GNU-Linux-x86/tests/TestFiles
CND_ARTIFACT_NAME_Debug=f2
CND_ARTIFACT_PATH_Debug=build/Debug/GNU-Linux-x86/tests/TestFiles/f2
CND_ARTIFACT_NAME_Debug=f1
CND_ARTIFACT_PATH_Debug=build/Debug/GNU-Linux-x86/tests/TestFiles/f1
CND_PACKAGE_DIR_Debug=dist/Debug/GNU-Linux-x86/package
CND_PACKAGE_NAME_Debug=scpi_parser.tar
CND_PACKAGE_PATH_Debug=dist/Debug/GNU-Linux-x86/package/scpi_parser.tar
netbeans/nbproject/Package-Debug.bash
@@ -12,8 +12,8 @@
CND_BUILDDIR=build
NBTMPDIR=${CND_BUILDDIR}/${CND_CONF}/${CND_PLATFORM}/tmp-packaging
TMPDIRNAME=tmp-packaging
OUTPUT_PATH=${TESTDIR}/TestFiles/f2
OUTPUT_BASENAME=f2
OUTPUT_PATH=${TESTDIR}/TestFiles/f1
OUTPUT_BASENAME=f1
PACKAGE_TOP_DIR=scpi_parser/
# Functions
netbeans/nbproject/configurations.xml
@@ -10,6 +10,7 @@
        <itemPath>../scpi/scpi_error.h</itemPath>
        <itemPath>../scpi/scpi_ieee488.h</itemPath>
        <itemPath>../scpi/scpi_minimal.h</itemPath>
        <itemPath>../scpi/scpi_units.h</itemPath>
        <itemPath>../scpi/scpi_utils.h</itemPath>
      </logicalFolder>
    </logicalFolder>
@@ -61,6 +62,8 @@
          <developmentMode>0</developmentMode>
          <incDir>
            <pElem>.</pElem>
            <pElem>.</pElem>
            <pElem>.</pElem>
          </incDir>
          <commandLine>-Wextra -g3 -O0</commandLine>
          <warningLevel>2</warningLevel>
@@ -68,11 +71,14 @@
        <ccTool>
          <incDir>
            <pElem>.</pElem>
            <pElem>.</pElem>
            <pElem>.</pElem>
          </incDir>
        </ccTool>
        <linkerTool>
          <output>${TESTDIR}/TestFiles/f2</output>
          <output>${TESTDIR}/TestFiles/f1</output>
          <linkerLibItems>
            <linkerLibStdlibItem>CUnit</linkerLibStdlibItem>
            <linkerLibStdlibItem>CUnit</linkerLibStdlibItem>
            <linkerLibStdlibItem>CUnit</linkerLibStdlibItem>
          </linkerLibItems>
@@ -91,26 +97,6 @@
                            group="bin"/>
        </packFileList>
      </packaging>
      <folder path="TestFiles/f1">
        <cTool>
          <incDir>
            <pElem>.</pElem>
            <pElem>.</pElem>
          </incDir>
        </cTool>
        <ccTool>
          <incDir>
            <pElem>.</pElem>
            <pElem>.</pElem>
          </incDir>
        </ccTool>
        <linkerTool>
          <output>${TESTDIR}/TestFiles/f1</output>
          <linkerLibItems>
            <linkerLibStdlibItem>CUnit</linkerLibStdlibItem>
          </linkerLibItems>
        </linkerTool>
      </folder>
      <folder path="TestFiles/f3">
        <cTool>
          <incDir>
netbeans/tests/test_scpi_utils.c
@@ -136,6 +136,54 @@
    CU_ASSERT_FALSE(compareStr("ABCD", 4, "abcd", 3));
}
void test_locateText() {
    char * v;
    char * b;
    size_t l;
    int result;
#define TEST_LOCATE_TEXT(s, ex_res, ex_off, ex_len)      \
    do {                                                \
        v = (s);                                        \
        b = NULL;                                       \
        l = 0;                                          \
        result = locateText(v, strlen(v), &b, &l);       \
        CU_ASSERT(result == ex_res);                    \
        if (result == TRUE) {                           \
                CU_ASSERT(b == (s + ex_off));           \
                CU_ASSERT(l == ex_len);                 \
        } else {                                        \
                CU_ASSERT(b == NULL);                   \
                CU_ASSERT(l == 0);                      \
        }                                               \
    } while(0)                                          \
    TEST_LOCATE_TEXT("", TRUE, 0, 0);
    TEST_LOCATE_TEXT("   ", TRUE, 3, 0);
    TEST_LOCATE_TEXT("a", TRUE, 0, 1);
    TEST_LOCATE_TEXT("ab", TRUE, 0, 2);
    TEST_LOCATE_TEXT("abc", TRUE, 0, 3);
    TEST_LOCATE_TEXT(" abc", TRUE, 1, 3);
    TEST_LOCATE_TEXT(" abc def", TRUE, 1, 7);
    TEST_LOCATE_TEXT(" abc def ", TRUE, 1, 7);
    TEST_LOCATE_TEXT("\"\"", TRUE, 1, 0);
    TEST_LOCATE_TEXT("\"a\"", TRUE, 1, 1);
    TEST_LOCATE_TEXT(" \"a\" ", TRUE, 2, 1);
    TEST_LOCATE_TEXT(" \"a\"  ", TRUE, 2, 1);
    TEST_LOCATE_TEXT(" \"a\"  ,", TRUE, 2, 1);
    TEST_LOCATE_TEXT(" \"a,b\"", TRUE, 2, 3);
    TEST_LOCATE_TEXT(" \"a,b\"     ,", TRUE, 2, 3);
    TEST_LOCATE_TEXT(" a b    ", TRUE, 1, 3);
    TEST_LOCATE_TEXT(" a b   ,", TRUE, 1, 3);
    TEST_LOCATE_TEXT(" \"a \" ", TRUE, 2, 2);
    TEST_LOCATE_TEXT(" \"a  ", FALSE, 0, 0);
    TEST_LOCATE_TEXT(" \"a\" a, a ", FALSE, 0, 0);
    TEST_LOCATE_TEXT(" \"a\" , a ", TRUE, 2, 1);
}
void test_locateStr() {
    char * v;
@@ -160,7 +208,6 @@
        }                                               \
    } while(0)                                          \
    TEST_LOCATE_STR("", TRUE, 0, 0);
    TEST_LOCATE_STR("   ", TRUE, 3, 0);
    TEST_LOCATE_STR("a", TRUE, 0, 1);
@@ -169,19 +216,35 @@
    TEST_LOCATE_STR(" abc", TRUE, 1, 3);
    TEST_LOCATE_STR(" abc def", TRUE, 1, 7);
    TEST_LOCATE_STR(" abc def ", TRUE, 1, 7);
    TEST_LOCATE_STR("\"\"", TRUE, 1, 0);
    TEST_LOCATE_STR("\"a\"", TRUE, 1, 1);
    TEST_LOCATE_STR(" \"a\" ", TRUE, 2, 1);
    TEST_LOCATE_STR(" \"a\"  ", TRUE, 2, 1);
    TEST_LOCATE_STR(" \"a\"  ,", TRUE, 2, 1);
    TEST_LOCATE_STR(" \"a,b\"", TRUE, 2, 3);
    TEST_LOCATE_STR(" \"a,b\"     ,", TRUE, 2, 3);
    TEST_LOCATE_STR("\"\"", TRUE, 0, 2);
    TEST_LOCATE_STR("\"a\"", TRUE, 0, 3);
    TEST_LOCATE_STR(" \"a\" ", TRUE, 1, 3);
    TEST_LOCATE_STR(" \"a\"  ", TRUE, 1, 3);
    TEST_LOCATE_STR(" \"a\"  ,", TRUE, 1, 3);
    TEST_LOCATE_STR(" \"a,b\"", TRUE, 1, 2);
    TEST_LOCATE_STR(" \"a,b\"     ,", TRUE, 1, 2);
    TEST_LOCATE_STR(" a b    ", TRUE, 1, 3);
    TEST_LOCATE_STR(" a b   ,", TRUE, 1, 3);
    TEST_LOCATE_STR(" \"a \" ", TRUE, 2, 2);
    TEST_LOCATE_STR(" \"a  ", FALSE, 0, 0);
    TEST_LOCATE_STR(" \"a\" a, a ", FALSE, 0, 0);
    TEST_LOCATE_STR(" \"a\" , a ", TRUE, 2, 1);
    TEST_LOCATE_STR(" \"a \" ", TRUE, 1, 4);
    TEST_LOCATE_STR(" \"a  ", TRUE, 1, 2);
    TEST_LOCATE_STR(" \"a\" a, a ", TRUE, 1, 5);
    TEST_LOCATE_STR(" \"a\" , a ", TRUE, 1, 3);
}
void test_matchPattern() {
    bool_t result;
#define TEST_MATCH_PATTERN(p, s, r)                             \
    do {                                                        \
        result = matchPattern(p, strlen(p), s, strlen(s));      \
        CU_ASSERT_EQUAL(result, r);                             \
    } while(0)                                                  \
    TEST_MATCH_PATTERN("A", "a", TRUE);
    TEST_MATCH_PATTERN("Ab", "a", TRUE);
    TEST_MATCH_PATTERN("Ab", "ab", TRUE);
    TEST_MATCH_PATTERN("Ab", "aB", TRUE);
    TEST_MATCH_PATTERN("AB", "a", FALSE);
}
int main() {
@@ -206,7 +269,9 @@
            || (NULL == CU_add_test(pSuite, "strToLong", test_strToLong))
            || (NULL == CU_add_test(pSuite, "strToDouble", test_strToDouble))
            || (NULL == CU_add_test(pSuite, "compareStr", test_compareStr))
            || (NULL == CU_add_test(pSuite, "locateText", test_locateText))
            || (NULL == CU_add_test(pSuite, "locateStr", test_locateStr))
            || (NULL == CU_add_test(pSuite, "matchPattern", test_matchPattern))
            ) {
        CU_cleanup_registry();
        return CU_get_error();
scpi/scpi.c
@@ -43,7 +43,6 @@
#include <stdint.h>
static size_t patternSeparatorPos(const char * pattern, size_t len);
static size_t patternSeparatorShortPos(const char * pattern, size_t len);
static size_t cmdSeparatorPos(const char * cmd, size_t len);
static size_t cmdTerminatorPos(const char * cmd, size_t len);
static size_t cmdlineSeparatorPos(const char * cmd, size_t len);
@@ -55,16 +54,6 @@
static void paramSkipBytes(scpi_context_t * context, size_t num);
static void paramSkipWhitespace(scpi_context_t * context);
static bool_t paramNext(scpi_context_t * context, bool_t mandatory);
#define max(a,b) \
   ({ __typeof__ (a) _a = (a); \
       __typeof__ (b) _b = (b); \
     _a > _b ? _a : _b; })
#define min(a,b) \
   ({ __typeof__ (a) _a = (a); \
       __typeof__ (b) _b = (b); \
     _a < _b ? _a : _b; })
/*
int _strnicmp(const char* s1, const char* s2, size_t len) {
@@ -98,23 +87,6 @@
    } else {
        return separator - pattern;
    }
}
/**
 * Pattern is composed from upper case an lower case letters. This function
 * search the first lowercase letter
 * @param pattern
 * @param len - max search length
 * @return position of separator or len
 */
size_t patternSeparatorShortPos(const char * pattern, size_t len) {
    size_t i;
    for (i = 0; (i < len) && pattern[i]; i++) {
        if (islower(pattern[i])) {
            return i;
        }
    }
    return i;
}
/**
@@ -221,10 +193,8 @@
    while (1) {
        int pattern_sep_pos = patternSeparatorPos(pattern_ptr, pattern_end - pattern_ptr);
        int cmd_sep_pos = cmdSeparatorPos(cmd_ptr, cmd_end - cmd_ptr);
        int pattern_sep_pos_short = patternSeparatorShortPos(pattern_ptr, pattern_sep_pos);
        if (compareStr(pattern_ptr, pattern_sep_pos, cmd_ptr, cmd_sep_pos) ||
                compareStr(pattern_ptr, pattern_sep_pos_short, cmd_ptr, cmd_sep_pos)) {
        if (matchPattern(pattern_ptr, pattern_sep_pos, cmd_ptr, cmd_sep_pos)) {
            pattern_ptr = pattern_ptr + pattern_sep_pos;
            cmd_ptr = cmd_ptr + cmd_sep_pos;
            result = TRUE;
@@ -262,7 +232,6 @@
    return result;
}
/**
 * Write data to SCPI output
@@ -326,6 +295,7 @@
            for (i = 0; context->cmdlist[i].pattern != NULL; i++) {
                if (cmdMatch(context->cmdlist[i].pattern, cmdline_ptr, cmd_len)) {
                    if (context->cmdlist[i].callback != NULL) {
                        context->error = FALSE;
                        context->paramlist.cmd = &context->cmdlist[i];
                        context->paramlist.parameters = cmdline_ptr + cmd_len;
                        context->paramlist.length = cmdlineSeparatorPos(context->paramlist.parameters, cmdline_end - context->paramlist.parameters);
@@ -338,7 +308,7 @@
                        writeNewLine(context); // conditionaly write new line
                        paramSkipWhitespace(context);
                        if (context->paramlist.length != 0) {
                        if (context->paramlist.length != 0 && !context->error) {
                            SCPI_ErrorPush(context, SCPI_ERROR_PARAMETER_NOT_ALLOWED);
                        }
@@ -537,6 +507,7 @@
            paramSkipBytes(context, 1);
            paramSkipWhitespace(context);
        } else {
            printf("******** :%c:\r\n", context->paramlist.parameters[0]);
            SCPI_ErrorPush(context, SCPI_ERROR_INVALID_SEPARATOR);
            return FALSE;
        }
@@ -553,29 +524,21 @@
 * @return 
 */
bool_t SCPI_ParamInt(scpi_context_t * context, int32_t * value, bool_t mandatory) {
    size_t len;
    char * param;
    size_t param_len;
    size_t num_len;
    if (!value) {
        return FALSE;
    }
    if (!paramNext(context, mandatory)) {
    if (!SCPI_ParamString(context, &param, &param_len, mandatory)) {
        return FALSE;
    }
       
    len = strToLong(context->paramlist.parameters, value);
    num_len = strToLong(param, value);
   
    if (len == 0) {
        if (mandatory) {
            SCPI_ErrorPush(context, SCPI_ERROR_SYNTAX);
        }
        return FALSE;
    } else {
        paramSkipBytes(context, len);
    }
    paramSkipWhitespace(context);
    if ((context->paramlist.length > 0) && (context->paramlist.parameters[0] != ',')) {
    if (num_len != param_len) {
        SCPI_ErrorPush(context, SCPI_ERROR_SUFFIX_NOT_ALLOWED);
        return FALSE;
    }
@@ -591,29 +554,21 @@
 * @return 
 */
bool_t SCPI_ParamDouble(scpi_context_t * context, double * value, bool_t mandatory) {
    size_t len;
    char * param;
    size_t param_len;
    size_t num_len;
    if (!value) {
        return FALSE;
    }
    if (!paramNext(context, mandatory)) {
    if (!SCPI_ParamString(context, &param, &param_len, mandatory)) {
        return FALSE;
    }
   
    len = strToDouble(context->paramlist.parameters, value);
    num_len = strToDouble(param, value);
    if (len == 0) {
        if (mandatory) {
            SCPI_ErrorPush(context, SCPI_ERROR_SYNTAX);
        }
        return FALSE;
    } else {
        paramSkipBytes(context, len);
    }
    paramSkipWhitespace(context);
    if ((context->paramlist.length > 0) && (context->paramlist.parameters[0] != ',')) {
    if (num_len != param_len) {
        SCPI_ErrorPush(context, SCPI_ERROR_SUFFIX_NOT_ALLOWED);
        return FALSE;
    }
@@ -642,6 +597,37 @@
    if (locateStr(context->paramlist.parameters, context->paramlist.length, value, &length)) {
        paramSkipBytes(context, length);
        paramSkipWhitespace(context);
        if (len) {
            *len = length;
        }
        return TRUE;
    }
    return FALSE;
}
/**
 * Parse text parameter (can be inside "")
 * @param context
 * @param value
 * @param len
 * @param mandatory
 * @return
 */
bool_t SCPI_ParamText(scpi_context_t * context, char ** value, size_t * len, bool_t mandatory) {
    size_t length;
    if (!value || !len) {
        return FALSE;
    }
    if (!paramNext(context, mandatory)) {
        return FALSE;
    }
    if (locateText(context->paramlist.parameters, context->paramlist.length, value, &length)) {
        paramSkipBytes(context, length);
        if (len) {
            *len = length;
        }
scpi/scpi.h
@@ -90,6 +90,7 @@
        scpi_interface_t * interface;
        int_fast16_t output_count;
        int_fast16_t input_count;
        bool_t error;
    };
scpi/scpi_error.c
@@ -73,9 +73,13 @@
        SCPI_RegSetBits(SCPI_REG_ESR, ESR_DER);
    }  
    
    if (context && context->interface && context->interface->error) {
    if (context) {
        if (context->interface && context->interface->error) {
        context->interface->error(context, err);
    }
        context->error = TRUE;
    }
}
/**
scpi/scpi_units.c
@@ -99,44 +99,65 @@
    SCPI_UNITS_LIST_END,
};
const scpi_special_number_def_t scpi_special_numbers_def[] = {
    { .name = "MIN", .type = SCPI_NUM_MIN},
    { .name = "MINIMUM", .type = SCPI_NUM_MIN},
    { .name = "MAX", .type = SCPI_NUM_MAX},
    { .name = "MAXIMUM", .type = SCPI_NUM_MAX},
    { .name = "DEF", .type = SCPI_NUM_DEF},
    { .name = "DEFAULT", .type = SCPI_NUM_DEF},
    { .name = "MINimum", .type = SCPI_NUM_MIN},
    { .name = "MAXimum", .type = SCPI_NUM_MAX},
    { .name = "DEFault", .type = SCPI_NUM_DEF},
    { .name = "UP", .type = SCPI_NUM_UP},
    { .name = "DOWN", .type = SCPI_NUM_DOWN},
    { .name = "NAN", .type = SCPI_NUM_NAN},
    { .name = "INF", .type = SCPI_NUM_INF},
    { .name = "NINF", .type = SCPI_NUM_NINF},
    SCPI_SPECIAL_NUMBERS_LIST_END,
};
static scpi_special_number_t translateSpecialNumber(const char * str, size_t len) {
static scpi_special_number_t translateSpecialNumber(const scpi_special_number_def_t * specs, const char * str, size_t len) {
    int i;
    for (i = 0; scpi_special_numbers_def[i].name != NULL; i++) {
        if (compareStr(str, len, scpi_special_numbers_def[i].name, strlen(scpi_special_numbers_def[i].name))) {
            return scpi_special_numbers_def[i].type;
    for (i = 0; specs[i].name != NULL; i++) {
        if (matchPattern(specs[i].name, strlen(specs[i].name), str, len)) {
            return specs[i].type;
        }
    }
    return SCPI_NUM_NUMBER;
}
static const scpi_unit_def_t * searchUnit(const char * unit, size_t len) {
static const char * translateSpecialNumberInverse(const scpi_special_number_def_t * specs, scpi_special_number_t type) {
    int i;
    for(i = 0; scpi_units_def[i].name != NULL; i++) {
        if (compareStr(unit, len, scpi_units_def[i].name, strlen(scpi_units_def[i].name))) {
            return &scpi_units_def[i];
    for (i = 0; specs[i].name != NULL; i++) {
        if (specs[i].type == type) {
            return specs[i].name;
        }
    }
    
    return NULL;
}
static bool_t transformNumber(const char * unit, size_t len, scpi_number_t * value) {
static const scpi_unit_def_t * translateUnit(const scpi_unit_def_t * units, const char * unit, size_t len) {
    int i;
    for (i = 0; units[i].name != NULL; i++) {
        if (compareStr(unit, len, units[i].name, strlen(units[i].name))) {
            return &units[i];
        }
    }
    return NULL;
}
static const char * translateUnitInverse(const scpi_unit_def_t * units, const scpi_unit_t unit) {
    int i;
    for (i = 0; units[i].name != NULL; i++) {
        if ((units[i].unit == unit) && (units[i].mult == 1)) {
            return units[i].name;
        }
    }
    return NULL;
}
static bool_t transformNumber(const scpi_unit_def_t * units, const char * unit, size_t len, scpi_number_t * value) {
    size_t s;
    const scpi_unit_def_t * unitDef;
    s = skipWhitespace(unit, len);
@@ -146,7 +167,7 @@
        return TRUE;
    }
    
    unitDef = searchUnit(unit + s, len - s);
    unitDef = translateUnit(units, unit + s, len - s);
    
    if (unitDef == NULL) {
        return FALSE;
@@ -171,19 +192,26 @@
    size_t len;
    size_t numlen;
    result = SCPI_ParamString(context, &param, &len, mandatory);
    // TODO: get scpi_special_numbers_def and scpi_units_def from context
    if (!result) {
        return FALSE;
    }
    result = SCPI_ParamString(context, &param, &len, mandatory);
    if (!value) {
        return FALSE;
    }
    if (!result) {
        if (mandatory) {
            return FALSE;
        } else {
            value->type = SCPI_NUM_DEF;
            return TRUE;
        }
    }
    value->unit = SCPI_UNIT_NONE;
    value->value = 0.0;
    value->type = translateSpecialNumber(param, len);
    value->type = translateSpecialNumber(scpi_special_numbers_def, param, len);
    if (value->type != SCPI_NUM_NUMBER) {
        // found special type
@@ -193,7 +221,7 @@
    numlen = strToDouble(param, &value->value);
    if (numlen <= len) {
        if (transformNumber(param + numlen, len - numlen, value)) {
        if (transformNumber(scpi_units_def, param + numlen, len - numlen, value)) {
            return TRUE;
        } else {
            SCPI_ErrorPush(context, SCPI_ERROR_INVALID_SUFFIX);            
@@ -203,3 +231,34 @@
}
size_t SCPI_NumberToStr(scpi_context_t * context, scpi_number_t * value, char * str, size_t len) {
    const char * type;
    const char * unit;
    size_t result;
    (void) context; // TODO: get scpi_special_numbers_def and scpi_units_def from context
    if (!value || !str) {
        return 0;
    }
    type = translateSpecialNumberInverse(scpi_special_numbers_def, value->type);
    if (type) {
        strncpy(str, type, len);
        return min(strlen(type), len);
    }
    result = doubleToStr(value->value, str, len);
    unit = translateUnitInverse(scpi_units_def, value->unit);
    if (unit) {
        strncat(str, " ", len);
        strncat(str, unit, len);
        result += strlen(unit) + 1;
    }
    return result;
}
scpi/scpi_units.h
@@ -94,7 +94,7 @@
    bool_t SCPI_ParamNumber(scpi_context_t * context, scpi_number_t * value, bool_t mandatory);
    size_t SCPI_NumberToStr(scpi_context_t * context, scpi_number_t * value, char * str, size_t len);
#ifdef    __cplusplus
}
scpi/scpi_utils.c
@@ -41,6 +41,8 @@
#include <string.h>
#include <ctype.h>
static size_t patternSeparatorShortPos(const char * pattern, size_t len);
/**
 * Find the first occurrence in str of a character in set.
 * @param str
@@ -152,7 +154,7 @@
    return FALSE;
}
bool_t locateStr(const char * str1, size_t len1, char ** str2, size_t * len2) {
bool_t locateText(const char * str1, size_t len1, char ** str2, size_t * len2) {
    size_t i;
    int quot = 0;
    int32_t strStart = -1;
@@ -230,6 +232,68 @@
    return valid;
}
bool_t locateStr(const char * str1, size_t len1, char ** str2, size_t * len2) {
    size_t i;
    int32_t strStart = -1;
    int32_t strStop = -1;
    int valid = 0;
    for (i = 0; i < len1; i++) {
        if ((strStart < 0) && isspace(str1[i])) {
            continue;
        }
        if (strStart < 0) {
            strStart = i;
        }
        if (!isspace(str1[i]) && (str1[i] != ',')) {
            strStop = i;
        }
        if (isspace(str1[i])) {
            continue;
        }
        if (str1[i] == ',') {
            valid = 1;
            if (strStop < 0) {
                strStop = i;
            }
            break;
        }
    }
    if (i == len1) {
        valid = 1;
        if (strStop < 0) {
            strStop = i;
        } else {
            strStop++;
        }
        if (strStart < 0) {
            strStart = i;
        }
    } else {
        strStop++;
    }
    if (valid) {
        if (str2) {
            *str2 = (char *) &str1[strStart];
        }
        if (len2) {
            *len2 = strStop - strStart;
        }
    }
    return valid;
}
/**
 * Count white spaces from the beggining
 * @param cmd - command
@@ -245,3 +309,35 @@
    }
    return len;
}
/**
 * Pattern is composed from upper case an lower case letters. This function
 * search the first lowercase letter
 * @param pattern
 * @param len - max search length
 * @return position of separator or len
 */
size_t patternSeparatorShortPos(const char * pattern, size_t len) {
    size_t i;
    for (i = 0; (i < len) && pattern[i]; i++) {
        if (islower(pattern[i])) {
            return i;
        }
    }
    return i;
}
/**
 * Match pattern and str. Pattern is in format UPPERCASElowercase
 * @param pattern
 * @param pattern_len
 * @param str
 * @param str_len
 * @return
 */
bool_t matchPattern(const char * pattern, size_t pattern_len, const char * str, size_t str_len) {
    int pattern_sep_pos_short = patternSeparatorShortPos(pattern, pattern_len);
    return compareStr(pattern, pattern_len, str, str_len) ||
            compareStr(pattern, pattern_sep_pos_short, str, str_len);
}
scpi/scpi_utils.h
@@ -50,8 +50,21 @@
    size_t doubleToStr(double val, char * str, size_t len);
    size_t strToLong(const char * str, int32_t * val);
    size_t strToDouble(const char * str, double * val);
    bool_t locateText(const char * str1, size_t len1, char ** str2, size_t * len2);
    bool_t locateStr(const char * str1, size_t len1, char ** str2, size_t * len2);
    size_t skipWhitespace(const char * cmd, size_t len);
    bool_t matchPattern(const char * pattern, size_t pattern_len, const char * str, size_t str_len);
#define max(a,b) \
   ({ __typeof__ (a) _a = (a); \
       __typeof__ (b) _b = (b); \
     _a > _b ? _a : _b; })
#define min(a,b) \
   ({ __typeof__ (a) _a = (a); \
       __typeof__ (b) _b = (b); \
     _a < _b ? _a : _b; })
#ifdef    __cplusplus
}
test-parser.c
@@ -42,22 +42,26 @@
#include "scpi/scpi_error.h"
#include "scpi/scpi_constants.h"
#include "scpi/scpi_minimal.h"
#include "scpi/scpi_utils.h"
#include "scpi/scpi_units.h"
int DMM_MeasureVoltageDcQ(scpi_context_t * context) {
    double param1, param2;
    fprintf(stderr, "meas:volt:dc "); // debug command name
    scpi_number_t param1, param2;
    char bf[15];
    fprintf(stderr, "meas:volt:dc\r\n"); // debug command name
    
    // read first parameter
    if (SCPI_ParamDouble(context, &param1, false)) {
        fprintf(stderr, "P1=%lf ", param1);
    // read first parameter if present
    if (SCPI_ParamNumber(context, &param1, false)) {
        SCPI_NumberToStr(context, &param1, bf, 15);
        fprintf(stderr, "\tP1=%s\r\n", bf);
    }
    
    // read second paraeter
    if (SCPI_ParamDouble(context, &param2, false)) {
        fprintf(stderr, "P2=%lf ", param2);
    // read second paraeter if present
    if (SCPI_ParamNumber(context, &param2, false)) {
        SCPI_NumberToStr(context, &param2, bf, 15);
        fprintf(stderr, "\tP2=%s\r\n", bf);
    }
    fprintf(stderr, "\r\n");
    SCPI_ResultDouble(context, 0);
    return 0;
}
@@ -144,42 +148,50 @@
/*
 * 
 */
#include "scpi/scpi_utils.h"
int main(int argc, char** argv) {
    (void) argc;
    (void) argv;
    int result;
   
    //printf("%.*s %s\r\n",  3, "asdadasdasdasdas", "b");
    SCPI_Init(&scpi_context, scpi_commands, &scpi_buffer, &scpi_interface);
    // // interactive demo
#define TEST_SCPI_INPUT(cmd)    result = SCPI_Input(&scpi_context, cmd, strlen(cmd))
    TEST_SCPI_INPUT("*CLS\r\n");
    TEST_SCPI_INPUT("*RST\r\n");
    TEST_SCPI_INPUT("MEAS:volt:DC? 12,50;*OPC\r\n");
    TEST_SCPI_INPUT("*IDN?\r\n");
    TEST_SCPI_INPUT("SYST:VERS?");
    TEST_SCPI_INPUT("\r\n*ID");
    TEST_SCPI_INPUT("N?");
    TEST_SCPI_INPUT(""); // emulate command timeout
    TEST_SCPI_INPUT("*ESE\r\n"); // cause error -109, missing parameter
    TEST_SCPI_INPUT("*ESE 0x20\r\n");
    TEST_SCPI_INPUT("IDN?\r\n"); // cause error -113, undefined header
    TEST_SCPI_INPUT("SYST:ERR?\r\n");
    TEST_SCPI_INPUT("SYST:ERR?\r\n");
    TEST_SCPI_INPUT("*STB?\r\n");
    TEST_SCPI_INPUT("*ESR?\r\n");
    TEST_SCPI_INPUT("*STB?\r\n");
    TEST_SCPI_INPUT("meas:volt:dc? 0.01 V, Default\r\n");
    TEST_SCPI_INPUT("meas:volt:dc?\r\n");
    TEST_SCPI_INPUT("meas:volt:dc? def, 0.00001\r\n");
    TEST_SCPI_INPUT("meas:volt:dc? 0.00001\r\n");
    //printf("%.*s %s\r\n",  3, "asdadasdasdasdas", "b");
    // interactive demo
    //  char smbuffer[10];
    //  while(1) {
    //          fgets(smbuffer, 10, stdin);
    //          SCPI_Input(&scpi_context, smbuffer, strlen(smbuffer));      
    //  }
       
    result = SCPI_Input(&scpi_context, "*CLS\r\n", 6);
    result = SCPI_Input(&scpi_context, "*RST\r\n", 6);
    result = SCPI_Input(&scpi_context, "MEAS:volt:DC? 12,50;*OPC\r\n", 26);
    result = SCPI_Input(&scpi_context, "*IDN?\r\n", 7);
    result = SCPI_Input(&scpi_context, "SYST:VERS?", 10);
    result = SCPI_Input(&scpi_context, "\r\n*ID", 5);
    result = SCPI_Input(&scpi_context, "N?", 2);
    result = SCPI_Input(&scpi_context, NULL, 0); // emulate command timeout
    result = SCPI_Input(&scpi_context, "*ESE\r\n", 6);
    result = SCPI_Input(&scpi_context, "*ESE 0x20\r\n", 11);
    result = SCPI_Input(&scpi_context, "IDN?\r\n", 6); // cause error -113, undefined header
    result = SCPI_Input(&scpi_context, "SYST:ERR?\r\n", 11);
    result = SCPI_Input(&scpi_context, "SYST:ERR?\r\n", 11);
    result = SCPI_Input(&scpi_context, "*STB?\r\n", 6);
    result = SCPI_Input(&scpi_context, "*ESR?\r\n", 6);
    result = SCPI_Input(&scpi_context, "*STB?\r\n", 6);
    return (EXIT_SUCCESS);
}