--- a/src/cmocka.c	2023-08-15 15:54:57.439010743 +0800
+++ cmocka/src/cmocka.c	2023-08-15 15:53:54.240452568 +0800
@@ -45,6 +45,9 @@
 #include <stdbool.h>
 #include <time.h>
 #include <float.h>
+#include <regex.h>
+#include <mqueue.h>
+#include <fcntl.h>
 
 /*
  * This allows to add a platform specific header file. Some embedded platforms
@@ -269,6 +272,7 @@
 const char *global_last_failed_assert = NULL;
 static int global_skip_test;
 static int global_stop_test;
+static int global_list_test;
 
 /* Keeps a map of the values that functions will have to return to provide */
 /* mocked interfaces. */
@@ -474,62 +478,18 @@
     return 0;
 }
 
-static int c_strmatch(const char *str, const char *pattern)
-{
-    int ok;
+static int c_regexmatch(const char *str, const char *pattern){
+    regex_t re;
+    int ret;
 
-    if (str == NULL || pattern == NULL) {
+    ret = regcomp(&re, pattern, REG_EXTENDED | REG_NOSUB);
+    if (ret != 0){
         return 0;
     }
+    ret = regexec(&re, str, 0, NULL, 0);
+    regfree(&re);
 
-    for (;;) {
-        /* Check if pattern is done */
-        if (*pattern == '\0') {
-            /* If string is at the end, we're good */
-            if (*str == '\0') {
-                return 1;
-            }
-
-            return 0;
-        }
-
-        if (*pattern == '*') {
-            /* Move on */
-            pattern++;
-
-            /* If we are at the end, everything is fine */
-            if (*pattern == '\0') {
-                return 1;
-            }
-
-            /* Try to match each position */
-            for (; *str != '\0'; str++) {
-                ok = c_strmatch(str, pattern);
-                if (ok) {
-                    return 1;
-                }
-            }
-
-            /* No match */
-            return 0;
-        }
-
-        /* If we are at the end, leave */
-        if (*str == '\0') {
-            return 0;
-        }
-
-        /* Check if we have a single wildcard or matching char */
-        if (*pattern != '?' && *str != *pattern) {
-            return 0;
-        }
-
-        /* Move string and pattern */
-        str++;
-        pattern++;
-    }
-
-    return 0;
+    return (ret == 0)? 1 : 0;
 }
 
 /* Create function results and expected parameter lists. */
@@ -1850,7 +1810,7 @@
 {
     if (result < 0) {
         if (error > 0) {
-            cmocka_print_error("%s < 0, errno(%d): %s\n",
+            cmocka_print_error("%s < 0, errno(%"PRIi32"): %s\n",
                            expression,
                            error,
                            strerror(error));
@@ -2667,21 +2627,21 @@
     print_message("[==========] %s: %zu test(s) run.\n",
                   group_name,
                   total_executed);
-    print_error("[  PASSED  ] %u test(s).\n",
+    print_message("[  PASSED  ] %u test(s).\n",
                 (unsigned)(total_passed));
 
     if (total_skipped) {
-        print_error("[  SKIPPED ] %s: %zu test(s), listed below:\n",
+        print_message("[  SKIPPED ] %s: %zu test(s), listed below:\n",
                     group_name,
                     total_skipped);
         for (i = 0; i < total_executed; i++) {
             struct CMUnitTestState *cmtest = &cm_tests[i];
 
             if (cmtest->status == CM_TEST_SKIPPED) {
-                print_error("[  SKIPPED ] %s\n", cmtest->test->name);
+                print_message("[  SKIPPED ] %s\n", cmtest->test->name);
             }
         }
-        print_error("\n %zu SKIPPED TEST(S)\n", total_skipped);
+        print_message("\n %zu SKIPPED TEST(S)\n", total_skipped);
     }
 
     if (total_failed) {
@@ -2918,6 +2878,11 @@
     global_skip_filter_pattern = pattern;
 }
 
+void cmocka_set_list_test(int list_test)
+{
+    global_list_test = list_test;
+}
+
 /****************************************************************************
  * TIME CALCULATIONS
  ****************************************************************************/
@@ -3194,10 +3159,26 @@
     double total_runtime = 0;
     size_t i;
     int rc;
+    mqd_t mq_id;
 
     /* Make sure uintmax_t is at least the size of a pointer. */
     assert_true(sizeof(uintmax_t) >= sizeof(void*));
 
+    /* Display name of testcase/testsuite but not run */
+    if (global_list_test) {
+        print_message("%s\n", group_name);
+        for (i = 0; i < num_tests; i++) {
+            if (tests[i].name != NULL &&
+                (tests[i].test_func != NULL
+                || tests[i].setup_func != NULL
+                || tests[i].teardown_func != NULL)) {
+                print_message("%4s%s\n", "", tests[i].name);
+            };
+        }
+
+        return 0;
+    }
+
     cm_tests = libc_calloc(1, sizeof(struct CMUnitTestState) * num_tests);
     if (cm_tests == NULL) {
         return -1;
@@ -3209,10 +3190,15 @@
             (tests[i].test_func != NULL
              || tests[i].setup_func != NULL
              || tests[i].teardown_func != NULL)) {
+            cm_tests[total_tests] = (struct CMUnitTestState) {
+                .test = &tests[i],
+                .status = CM_TEST_NOT_STARTED,
+                .state = NULL,
+            };
             if (global_test_filter_pattern != NULL) {
                 int match;
 
-                match = c_strmatch(tests[i].name, global_test_filter_pattern);
+                match = c_regexmatch(tests[i].name, global_test_filter_pattern);
                 if (!match) {
                     continue;
                 }
@@ -3220,16 +3206,11 @@
             if (global_skip_filter_pattern != NULL) {
                 int match;
 
-                match = c_strmatch(tests[i].name, global_skip_filter_pattern);
+                match = c_regexmatch(tests[i].name, global_skip_filter_pattern);
                 if (match) {
-                    continue;
+                    cm_tests[i].status = CM_TEST_SKIPPED;
                 }
             }
-            cm_tests[total_tests] = (struct CMUnitTestState) {
-                .test = &tests[i],
-                .status = CM_TEST_NOT_STARTED,
-                .state = NULL,
-            };
             total_tests++;
         }
     }
@@ -3261,9 +3242,11 @@
                 cmtest->state = cmtest->test->initial_state;
             }
 
-            rc = cmocka_run_one_tests(cmtest);
+            if (cmtest->status != CM_TEST_SKIPPED) {
+                rc = cmocka_run_one_tests(cmtest);
+                total_runtime += cmtest->runtime;
+            }
             total_executed++;
-            total_runtime += cmtest->runtime;
             if (rc == 0) {
                 switch (cmtest->status) {
                     case CM_TEST_PASSED:
@@ -3296,7 +3279,7 @@
                         break;
                 }
             } else {
-                char err_msg[2048] = {0};
+                char err_msg[256] = {0};
 
                 snprintf(err_msg, sizeof(err_msg),
                          "Could not run test: %s",
@@ -3347,6 +3330,24 @@
                           total_runtime,
                           cm_tests);
 
+    mq_id = mq_open(CMOCKA_QUEUE_NAME, O_WRONLY);
+    if (mq_id != (mqd_t)-1) {
+        struct cm_summary_counter summary_send = {total_tests,
+                                                total_failed,
+                                                total_passed,
+                                                total_executed,
+                                                total_errors,
+                                                total_skipped};
+        if (mq_send(mq_id,
+                    (const char *)&summary_send,
+                    sizeof(summary_send),
+                    0) < 0) {
+            perror("mq_send");
+        }
+
+        mq_close(mq_id);
+    }
+
     for (i = 0; i < total_tests; i++) {
         vcm_free_error(discard_const_p(char, cm_tests[i].error_message));
     }
--- a/include/cmocka.h	2022-09-06 02:12:20.000000000 +0800
+++ cmocka/include/cmocka.h	2023-08-15 15:53:54.240452568 +0800
@@ -2279,6 +2279,20 @@
     uintmax_t check_value_data;
 } CheckParameterEvent;
 
+/* Mutiple suite run summary counter. */
+#define CMOCKA_QUEUE_NAME "/tmp/cmocka"
+#define CMOCKA_MAX_MSG_SIZE 128
+#define CMOCKA_MAX_MSG_NUM 15
+
+typedef struct cm_summary_counter {
+    int tests;
+    int failed;
+    int passed;
+    int executed;
+    int errors;
+    int skipped;
+} cm_summary_counter;
+
 /* Used by expect_assert_failure() and mock_assert(). */
 extern int global_expecting_assert;
 extern jmp_buf global_expect_assert_env;
@@ -2517,6 +2531,15 @@
  */
 void cmocka_set_skip_filter(const char *pattern);
 
+/**
+ * @brief Set a flag to list testcase name only.
+ *
+ * This set global list_tests flag to indicate whether to list only,
+ * if list_tests is 1, list only.
+ *
+ * @param list_tests  0 or 1.
+ */
+void cmocka_set_list_test(int list_test);
 /** @} */
 
 #endif /* CMOCKA_H_ */
