From efbd933813a6d273962a3957e17fdf4fb40f5b04 Mon Sep 17 00:00:00 2001
From: Jan Breuer <jan.breuer@jaybee.cz>
Date: 周五, 19 4月 2013 17:20:17 +0800
Subject: [PATCH] Resolve bug with short commands

---
 .gitignore                     |    1 
 libscpi/src/parser.c           |  104 --------------------
 libscpi/test/test_scpi_utils.c |   22 ++++
 libscpi/src/utils.h            |    2 
 libscpi/src/utils.c            |  127 +++++++++++++++++++++++++
 5 files changed, 155 insertions(+), 101 deletions(-)

diff --git a/.gitignore b/.gitignore
index ab6d275..cdb9024 100644
--- a/.gitignore
+++ b/.gitignore
@@ -16,6 +16,7 @@
 *.out
 *.app
 *.test
+examples/*/test
 
 # Backup files
 *~
diff --git a/libscpi/src/parser.c b/libscpi/src/parser.c
index 2ff12c2..9261f66 100644
--- a/libscpi/src/parser.c
+++ b/libscpi/src/parser.c
@@ -43,14 +43,11 @@
 #include "scpi/error.h"
 
 
-static size_t patternSeparatorPos(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);
 static const char * cmdlineSeparator(const char * cmd, size_t len);
 static const char * cmdlineTerminator(const char * cmd, size_t len);
 static const char * cmdlineNext(const char * cmd, size_t len);
-static bool_t cmdMatch(const char * pattern, const char * cmd, size_t len);
 
 static void paramSkipBytes(scpi_t * context, size_t num);
 static void paramSkipWhitespace(scpi_t * context);
@@ -73,40 +70,6 @@
     return result;
 }
  */
-
-/**
- * Find pattern separator position
- * @param pattern
- * @param len - max search length
- * @return position of separator or len
- */
-size_t patternSeparatorPos(const char * pattern, size_t len) {
-
-    char * separator = strnpbrk(pattern, len, "?:[]");
-    if (separator == NULL) {
-        return len;
-    } else {
-        return separator - pattern;
-    }
-}
-
-/**
- * Find command separator position
- * @param cmd - input command
- * @param len - max search length
- * @return position of separator or len
- */
-size_t cmdSeparatorPos(const char * cmd, size_t len) {
-    char * separator = strnpbrk(cmd, len, ":?");
-    size_t result;
-    if (separator == NULL) {
-        result = len;
-    } else {
-        result = separator - cmd;
-    }
-
-    return result;
-}
 
 /**
  * Find command termination character
@@ -174,67 +137,6 @@
 }
 
 /**
- * Compare pattern and command
- * @param pattern
- * @param cmd - command
- * @param len - max search length
- * @return TRUE if pattern matches, FALSE otherwise
- */
-bool_t cmdMatch(const char * pattern, const char * cmd, size_t len) {
-    int result = FALSE;
-
-    const char * pattern_ptr = pattern;
-    int pattern_len = SCPI_strnlen(pattern, len);
-    const char * pattern_end = pattern + pattern_len;
-
-    const char * cmd_ptr = cmd;
-    size_t cmd_len = SCPI_strnlen(cmd, len);
-    const char * cmd_end = cmd + cmd_len;
-
-    while (1) {
-        int pattern_sep_pos = patternSeparatorPos(pattern_ptr, pattern_end - pattern_ptr);
-        int cmd_sep_pos = cmdSeparatorPos(cmd_ptr, cmd_end - cmd_ptr);
-
-        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;
-
-            /* command is complete */
-            if ((pattern_ptr == pattern_end) && (cmd_ptr >= cmd_end)) {
-                break;
-            }
-
-            /* pattern complete, but command not */
-            if ((pattern_ptr == pattern_end) && (cmd_ptr < cmd_end)) {
-                result = FALSE;
-                break;
-            }
-
-            /* command complete, but pattern not */
-            if (cmd_ptr >= cmd_end) {
-                result = FALSE;
-                break;
-            }
-
-            /* both command and patter contains command separator at this position */
-            if ((pattern_ptr[0] == cmd_ptr[0]) && ((pattern_ptr[0] == ':') || (pattern_ptr[0] == '?'))) {
-                pattern_ptr = pattern_ptr + 1;
-                cmd_ptr = cmd_ptr + 1;
-            } else {
-                result = FALSE;
-                break;
-            }
-        } else {
-            result = FALSE;
-            break;
-        }
-    }
-
-    return result;
-}
-
-/**
  * Write data to SCPI output
  * @param context
  * @param data
@@ -272,9 +174,9 @@
 }
 
 /**
- * Zapis nove radky na SCPI vystup
+ * Conditionaly write "New Line"
  * @param context
- * @return pocet zapsanych znaku
+ * @return number of characters written
  */
 static size_t writeNewLine(scpi_t * context) {
     if (context->output_count > 0) {
@@ -329,7 +231,7 @@
 
     for (i = 0; context->cmdlist[i].pattern != NULL; i++) {
         cmd = &context->cmdlist[i];
-        if (cmdMatch(cmd->pattern, cmdline_ptr, cmd_len)) {
+        if (matchCommand(cmd->pattern, cmdline_ptr, cmd_len)) {
             context->paramlist.cmd = cmd;
             context->paramlist.parameters = cmdline_ptr + cmd_len;
             context->paramlist.length = cmdline_len - cmd_len;
diff --git a/libscpi/src/utils.c b/libscpi/src/utils.c
index 8880636..89c7a56 100644
--- a/libscpi/src/utils.c
+++ b/libscpi/src/utils.c
@@ -42,6 +42,8 @@
 #include "utils.h"
 
 static size_t patternSeparatorShortPos(const char * pattern, size_t len);
+static size_t patternSeparatorPos(const char * pattern, size_t len);
+static size_t cmdSeparatorPos(const char * cmd, size_t len);
 
 /**
  * Find the first occurrence in str of a character in set.
@@ -372,6 +374,35 @@
     return len;
 }
 
+/** 
+ * is colon or not.  add by hmm 2013.4.1
+ * @param cmd - command
+ * @return
+ */
+static bool_t iscolon(const char * cmd) {
+    char* pColon = ":";
+    if(0 == SCPI_strncasecmp(cmd, pColon, 1))
+    {
+        return TRUE;
+    }
+    return FALSE;
+}
+
+/**
+ * Count colon from the beggining  add by hmm 2013.4.1
+ * @param cmd - command
+ * @param len - max search length
+ * @return number of colon
+ */
+size_t skipColon(const char * cmd, size_t len) {
+    size_t i;
+    for (i = 0; i < len; i++) {
+        if (!iscolon(&cmd[i])) {
+            return i;
+        }
+    }
+    return len;
+}
 
 /**
  * Pattern is composed from upper case an lower case letters. This function
@@ -391,6 +422,41 @@
 }
 
 /**
+ * Find pattern separator position
+ * @param pattern
+ * @param len - max search length
+ * @return position of separator or len
+ */
+size_t patternSeparatorPos(const char * pattern, size_t len) {
+    
+    char * separator = strnpbrk(pattern, len, "?:[]");
+    if (separator == NULL) {
+        return len;
+    } else {
+        return separator - pattern;
+    }
+}
+
+/**
+ * Find command separator position
+ * @param cmd - input command
+ * @param len - max search length
+ * @return position of separator or len
+ */
+size_t cmdSeparatorPos(const char * cmd, size_t len) {
+    char * separator = strnpbrk(cmd, len, ":?");
+    size_t result;
+    if (separator == NULL) {
+        result = len;
+    } else {
+        result = separator - cmd;
+    }
+    
+    return result;
+}
+
+
+/**
  * Match pattern and str. Pattern is in format UPPERCASElowercase
  * @param pattern
  * @param pattern_len
@@ -404,6 +470,67 @@
             compareStr(pattern, pattern_sep_pos_short, str, str_len);
 }
 
+/**
+ * Compare pattern and command
+ * @param pattern
+ * @param cmd - command
+ * @param len - max search length
+ * @return TRUE if pattern matches, FALSE otherwise
+ */
+bool_t matchCommand(const char * pattern, const char * cmd, size_t len) {
+    int result = FALSE;
+    
+    const char * pattern_ptr = pattern;
+    int pattern_len = strlen(pattern);
+    const char * pattern_end = pattern + pattern_len;
+    
+    const char * cmd_ptr = cmd;
+    size_t cmd_len = SCPI_strnlen(cmd, len);
+    const char * cmd_end = cmd + cmd_len;
+    
+    while (1) {
+        int pattern_sep_pos = patternSeparatorPos(pattern_ptr, pattern_end - pattern_ptr);
+        int cmd_sep_pos = cmdSeparatorPos(cmd_ptr, cmd_end - cmd_ptr);
+        
+        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;
+            
+            /* command is complete */
+            if ((pattern_ptr == pattern_end) && (cmd_ptr >= cmd_end)) {
+                break;
+            }
+            
+            /* pattern complete, but command not */
+            if ((pattern_ptr == pattern_end) && (cmd_ptr < cmd_end)) {
+                result = FALSE;
+                break;
+            }
+            
+            /* command complete, but pattern not */
+            if (cmd_ptr >= cmd_end) {
+                result = FALSE;
+                break;
+            }
+            
+            /* both command and patter contains command separator at this position */
+            if ((pattern_ptr[0] == cmd_ptr[0]) && ((pattern_ptr[0] == ':') || (pattern_ptr[0] == '?'))) {
+                pattern_ptr = pattern_ptr + 1;
+                cmd_ptr = cmd_ptr + 1;
+            } else {
+                result = FALSE;
+                break;
+            }
+        } else {
+            result = FALSE;
+            break;
+        }
+    }
+    
+    return result;
+}
+
 
 #if !HAVE_STRNLEN
 /* use FreeBSD strnlen */
diff --git a/libscpi/src/utils.h b/libscpi/src/utils.h
index b1e24a0..e4f4137 100644
--- a/libscpi/src/utils.h
+++ b/libscpi/src/utils.h
@@ -56,7 +56,9 @@
     bool_t locateText(const char * str1, size_t len1, const char ** str2, size_t * len2) LOCAL;
     bool_t locateStr(const char * str1, size_t len1, const char ** str2, size_t * len2) LOCAL;
     size_t skipWhitespace(const char * cmd, size_t len) LOCAL;
+    size_t skipColon(const char * cmd, size_t len) LOCAL;
     bool_t matchPattern(const char * pattern, size_t pattern_len, const char * str, size_t str_len) LOCAL;
+    bool_t matchCommand(const char * pattern, const char * cmd, size_t len) LOCAL;
 
 #if !HAVE_STRNLEN
     size_t BSD_strnlen(const char *s, size_t maxlen);
diff --git a/libscpi/test/test_scpi_utils.c b/libscpi/test/test_scpi_utils.c
index 059cc97..1081d6e 100644
--- a/libscpi/test/test_scpi_utils.c
+++ b/libscpi/test/test_scpi_utils.c
@@ -250,6 +250,27 @@
     TEST_MATCH_PATTERN("AB", "a", FALSE);
 }
 
+void test_matchCommand() {
+    bool_t result;
+    
+    #define TEST_MATCH_COMMAND(p, s, r)                         \
+    do {                                                        \
+        result = matchCommand(p, s, strlen(s));                 \
+        CU_ASSERT_EQUAL(result, r);                             \
+    } while(0)                                                  \
+
+    TEST_MATCH_COMMAND("A", "a", TRUE);
+    TEST_MATCH_COMMAND("Ab", "a", TRUE);
+    TEST_MATCH_COMMAND("Ab", "ab", TRUE);
+    TEST_MATCH_COMMAND("Ab", "aB", TRUE);
+    TEST_MATCH_COMMAND("AB", "a", FALSE);
+    TEST_MATCH_COMMAND("ABc:AACddd", "ab:aac", TRUE);
+    TEST_MATCH_COMMAND("ABc:AACddd", "abc:aac", TRUE);
+    TEST_MATCH_COMMAND("ABc:AACddd", "abc:aacddd", TRUE);
+    TEST_MATCH_COMMAND("ABc:AACddd", "abc:aacdd", FALSE);
+    TEST_MATCH_COMMAND("ABc:AACddd", "a:aac", FALSE);
+}
+
 int main() {
     CU_pSuite pSuite = NULL;
 
@@ -275,6 +296,7 @@
             || (NULL == CU_add_test(pSuite, "locateText", test_locateText))
             || (NULL == CU_add_test(pSuite, "locateStr", test_locateStr))
             || (NULL == CU_add_test(pSuite, "matchPattern", test_matchPattern))
+            || (NULL == CU_add_test(pSuite, "matchCommand", test_matchCommand))
             ) {
         CU_cleanup_registry();
         return CU_get_error();

--
Gitblit v1.9.1