char *fmt;
};
-static void replace_fmt(char **base, size_t off, const char *new)
-{
- size_t newlen, baselen;
- char *tmp;
-
- newlen = strlen(new);
- baselen = strlen(*base);
-
- if (newlen > 2) {
- /*
- * FIXME This should be done with realloc() but valgrind
- * is reporting problems with using uninitialized memory.
- *
- * Also: it could be made more efficient by allocating more
- * memory at the beginning and then doubling the size of the
- * buffer once the previous one is exhausted.
- */
- tmp = malloc(baselen + newlen + 1);
- if (!tmp)
- die("out of memory");
-
- memset(tmp, 0, baselen + newlen + 1);
- strcpy(tmp, *base);
- free(*base);
- *base = tmp;
- }
-
- memmove(*base + off + newlen, *base + off + 2, baselen - off - 2);
- strncpy(*base + off, new, newlen);
-
- if (newlen < 2)
- *(*base + baselen - 1) = '\0';
-}
-
static void event_print_custom(int type, const struct timespec *ts,
struct callback_data *data)
{
- char repbuf[64], *str, *pos, fmt;
- size_t off;
+ char *prev, *curr, fmt;
- str = strdup(data->fmt);
- if (!str)
- die("out of memory");
-
- for (off = 0;;) {
- pos = strchr(str + off, '%');
- if (!pos)
+ for (prev = curr = data->fmt;;) {
+ curr = strchr(curr, '%');
+ if (!curr) {
+ fputs(prev, stdout);
break;
+ }
- fmt = *(pos + 1);
- off = pos - str;
+ if (prev != curr)
+ fwrite(prev, curr - prev, 1, stdout);
- if (fmt == '%') {
- memmove(str + off, str + off + 1, strlen(str) - off);
- off += 1;
- continue;
- }
+ fmt = *(curr + 1);
switch (fmt) {
case 'o':
- snprintf(repbuf, sizeof(repbuf), "%u", data->offset);
- replace_fmt(&str, off, repbuf);
+ printf("%u", data->offset);
break;
case 'e':
if (type == GPIOD_EVENT_CB_RISING_EDGE)
- snprintf(repbuf, sizeof(repbuf), "1");
+ fputc('1', stdout);
else
- snprintf(repbuf, sizeof(repbuf), "0");
- replace_fmt(&str, off, repbuf);
+ fputc('0', stdout);
break;
case 's':
- snprintf(repbuf, sizeof(repbuf), "%ld", ts->tv_sec);
- replace_fmt(&str, off, repbuf);
+ printf("%ld", ts->tv_sec);
break;
case 'n':
- snprintf(repbuf, sizeof(repbuf), "%ld", ts->tv_nsec);
- replace_fmt(&str, off, repbuf);
+ printf("%ld", ts->tv_nsec);
break;
+ case '%':
+ fputc('%', stdout);
+ break;
+ case '\0':
+ fputc('%', stdout);
+ goto end;
default:
- off += 2;
- continue;
+ fwrite(curr, 2, 1, stdout);
+ break;
}
- off += strlen(repbuf);
+ curr += 2;
+ prev = curr;
}
- printf("%s\n", str);
- free(str);
+end:
+ fputc('\n', stdout);
}
static void event_print_human_readable(int type, const struct timespec *ts,
"tools: gpiomon - custom output format: timestamp",
0, { 8, 8 });
-static void gpiomon_custom_format_double_percent(void)
+static void gpiomon_custom_format_double_percent_sign(void)
+{
+ test_tool_run("gpiomon", "--num-events=1", "--format=%%",
+ test_chip_name(0), "3", (char *)NULL);
+ test_set_event(0, 3, TEST_EVENT_RISING, 100);
+ test_tool_wait();
+
+ TEST_ASSERT(test_tool_exited());
+ TEST_ASSERT_RET_OK(test_tool_exit_status());
+ TEST_ASSERT_NOT_NULL(test_tool_stdout());
+ TEST_ASSERT_NULL(test_tool_stderr());
+ TEST_ASSERT_STR_EQ(test_tool_stdout(), "%\n");
+}
+TEST_DEFINE(gpiomon_custom_format_double_percent_sign,
+ "tools: gpiomon - custom output format: double percent sign",
+ 0, { 8, 8 });
+
+static void gpiomon_custom_format_double_percent_sign_and_spec(void)
{
test_tool_run("gpiomon", "--num-events=1", "--format=%%e",
test_chip_name(0), "3", (char *)NULL);
TEST_ASSERT_NULL(test_tool_stderr());
TEST_ASSERT_STR_EQ(test_tool_stdout(), "%e\n");
}
-TEST_DEFINE(gpiomon_custom_format_double_percent,
- "tools: gpiomon - custom output format: double percent",
+TEST_DEFINE(gpiomon_custom_format_double_percent_sign_and_spec,
+ "tools: gpiomon - custom output format: double percent sign with specifier",
+ 0, { 8, 8 });
+
+static void gpiomon_custom_format_single_percent_sign(void)
+{
+ test_tool_run("gpiomon", "--num-events=1", "--format=%",
+ test_chip_name(0), "3", (char *)NULL);
+ test_set_event(0, 3, TEST_EVENT_RISING, 100);
+ test_tool_wait();
+
+ TEST_ASSERT(test_tool_exited());
+ TEST_ASSERT_RET_OK(test_tool_exit_status());
+ TEST_ASSERT_NOT_NULL(test_tool_stdout());
+ TEST_ASSERT_NULL(test_tool_stderr());
+ TEST_ASSERT_STR_EQ(test_tool_stdout(), "%\n");
+}
+TEST_DEFINE(gpiomon_custom_format_single_percent_sign,
+ "tools: gpiomon - custom output format: single percent sign",
+ 0, { 8, 8 });
+
+static void gpiomon_custom_format_single_percent_sign_between_chars(void)
+{
+ test_tool_run("gpiomon", "--num-events=1", "--format=foo % bar",
+ test_chip_name(0), "3", (char *)NULL);
+ test_set_event(0, 3, TEST_EVENT_RISING, 100);
+ test_tool_wait();
+
+ TEST_ASSERT(test_tool_exited());
+ TEST_ASSERT_RET_OK(test_tool_exit_status());
+ TEST_ASSERT_NOT_NULL(test_tool_stdout());
+ TEST_ASSERT_NULL(test_tool_stderr());
+ TEST_ASSERT_STR_EQ(test_tool_stdout(), "foo % bar\n");
+}
+TEST_DEFINE(gpiomon_custom_format_single_percent_sign_between_chars,
+ "tools: gpiomon - custom output format: single percent sign between other characters",
0, { 8, 8 });
static void gpiomon_custom_format_unknown_specifier(void)