aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlonkaars <loek@pipeframe.xyz>2024-05-24 17:47:00 +0200
committerlonkaars <loek@pipeframe.xyz>2024-05-24 17:47:00 +0200
commit1a92ed5075aba4b41fe34422d21a2c66cdf1d4c9 (patch)
treea66d2dae13ab7c214da7b9ccf4701f0b7817c2e5
parent31c30df2a24a45c69a7c5c2f594fa3a9a835b1fb (diff)
WIP `send` command
-rw-r--r--client/CMakeLists.txt1
-rw-r--r--client/cmd.cpp58
-rw-r--r--client/cmd.h10
-rw-r--r--client/parse.cpp32
-rw-r--r--client/parse.h38
-rw-r--r--client/rl.cpp47
6 files changed, 145 insertions, 41 deletions
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
index c526345..35a55b6 100644
--- a/client/CMakeLists.txt
+++ b/client/CMakeLists.txt
@@ -13,6 +13,7 @@ add_executable(pbc
rl.cpp
sock.cpp
cmd.cpp
+ parse.cpp
)
target_link_libraries(pbc
diff --git a/client/cmd.cpp b/client/cmd.cpp
index 0a73dad..4a2c8a3 100644
--- a/client/cmd.cpp
+++ b/client/cmd.cpp
@@ -4,6 +4,12 @@
#include "cmd.h"
#include "sock.h"
+#include "parse.h"
+
+char* consume_token(char* input, const char* ifs) {
+ strtok(input, ifs);
+ return strtok(NULL, "\0");
+}
void cmd_exit(char*) {
exit(EXIT_SUCCESS);
@@ -11,22 +17,46 @@ void cmd_exit(char*) {
void cmd_test(char*) {
const char* data = "Hello world!";
- i2c_send(0x39, (char*) data, strlen(data));
+ i2c_send(0x39, data, strlen(data));
}
void cmd_help(char*) {
- printf("List of available commands:\n");
- for (size_t i = 0; i < cmds_length; i++) {
- struct cmd cmd = cmds[i];
- printf(" %-*s", 10, cmd.name);
- if (cmd.info != NULL)
- printf(" %s", cmd.info);
- printf("\n");
- }
-
- printf(
- "\n"
- "You can also use the TAB key to autocomplete commands\n"
- );
+ printf("List of available commands:\n");
+ for (size_t i = 0; i < cmds_length; i++) {
+ struct cmd cmd = cmds[i];
+ printf(" %-*s", 10, cmd.name);
+ if (cmd.info != NULL)
+ printf(" %s", cmd.info);
+ printf("\n");
+ }
+
+ printf(
+ "\n"
+ "You can also use the TAB key to autocomplete commands\n"
+ );
+}
+
+void cmd_send(char* addr_str) {
+ char* data_str = consume_token(addr_str, IFS);
+
+ char* end;
+ uint16_t addr = strtol(addr_str, &end, 0);
+ if (addr_str + strlen(addr_str) != end) {
+ printf("address format error\n");
+ return;
+ }
+
+ char* data;
+ size_t data_size;
+ if (strtodata(data_str, &data, &data_size)) {
+ printf("data format error at index %d:\n%s\n%*s^\n",
+ (int) data_size, data_str, (int) data_size, "");
+ return;
+ }
+
+ // printf("(0x%02x) -> \"%.*s\"\n", addr, data_size, data);
+ i2c_send(addr, data, data_size);
+
+ free(data);
}
diff --git a/client/cmd.h b/client/cmd.h
index 7ec67fc..9d20328 100644
--- a/client/cmd.h
+++ b/client/cmd.h
@@ -35,11 +35,11 @@ static const struct cmd cmds[] = {
.name = "help",
.info = "show this help",
},
- // {
- // .handle = cmd_send,
- // .name = "send",
- // .info = "[debug] send raw message",
- // },
+ {
+ .handle = cmd_send,
+ .name = "send",
+ .info = "[debug] send raw message",
+ },
// {
// .handle = cmd_status,
// .name = "status",
diff --git a/client/parse.cpp b/client/parse.cpp
new file mode 100644
index 0000000..d15207c
--- /dev/null
+++ b/client/parse.cpp
@@ -0,0 +1,32 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "parse.h"
+
+static unsigned ifsrun(const char* input, const char* ift) {
+ unsigned i;
+ for (i = 0; input[i] != '\0' && strchr(ift, input[i]); i++);
+ return i;
+}
+
+int strtodata(const char* str, char** data, size_t* size) {
+ const char* ifs = IFS;
+ *size = 0;
+ size_t i;
+ size_t str_len = strlen(str);
+
+ // TODO: finish this parser
+ // for (i = 0; i < str_len; i++) {
+ // unsigned ifs_run = ifsrun(&str[i], ifs);
+ //
+ // }
+
+ *size = str_len;
+
+ *data = (char*) malloc(*size);
+
+ memcpy(*data, str, *size);
+
+ return 0;
+}
+
diff --git a/client/parse.h b/client/parse.h
new file mode 100644
index 0000000..ac06446
--- /dev/null
+++ b/client/parse.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include <stddef.h>
+
+#define IFS " \t\n"
+
+/**
+ * \brief modify \p token to point to the first token when broken up on \p ifs
+ * and return the remaining data
+ *
+ * \p token will be null-terminated to indicate the end of the first token. A
+ * pointer to the remaining line after the NULL byte is returned, or NULL when
+ * the end of the string has been reached.
+ *
+ * \param token input string
+ * \param ifs string containing field separators
+ *
+ * \return the remaining data after \p token and the first \p ifs
+ */
+char* consume_token(char* token, const char* ifs);
+
+/**
+ * \brief convert string with literals into raw data
+ *
+ * \param str input string containing literals
+ * \param data pointer to \c char* that will store the resulting data
+ * \param size size of \p data
+ *
+ * \return 0 if the string was parsed succesfully, or 1 if the string could not
+ * be parsed succesfully
+ *
+ * \note The pointer that \p data refers to will not be initialized by this
+ * function if parsing fails
+ * \note \p size will contain the index of \p str where the first invalid data
+ * was found if parsing fails
+ */
+int strtodata(const char* str, char** data, size_t* size);
+
diff --git a/client/rl.cpp b/client/rl.cpp
index 6073500..3f93e99 100644
--- a/client/rl.cpp
+++ b/client/rl.cpp
@@ -8,13 +8,14 @@
#include "rl.h"
#include "cmd.h"
+#include "parse.h"
void rl_printf(const char *fmt, ...) {
// save line
char* saved_line = rl_copy_text(0, rl_end);
int saved_point = rl_point;
int saved_end = rl_end;
-
+
// clear line
rl_save_prompt();
rl_replace_line("", 0);
@@ -36,34 +37,38 @@ void rl_printf(const char *fmt, ...) {
free(saved_line);
}
-static bool cli_cmd(char* line) {
- char* cmd = strtok(line, " \t\n");
+static void cli_cmd(char* cmd) {
+ char* line = consume_token(cmd, IFS);
+
for (size_t i = 0; i < cmds_length; i++) {
- if (strncmp(cmds[i].name, cmd, strlen(cmd)) != 0) continue;
+ if (strncmp(cmds[i].name, cmd, strlen(cmd)) != 0)
+ continue;
+
cmds[i].handle(line);
- return true;
+ return;
}
- return false;
+
+ printf("unknown command!\n");
}
static char* rl_completion_entries(const char *text, int state) {
- static size_t i = 0;
- if (state == 0) i = 0;
-
- while (i < cmds_length) {
- struct cmd cmd = cmds[i];
- i++;
- if (strncmp(text, cmd.name, strlen(text)) == 0) {
- return strdup(cmd.name);
- }
- }
-
- return NULL;
+ static size_t i = 0;
+ if (state == 0) i = 0;
+
+ while (i < cmds_length) {
+ struct cmd cmd = cmds[i];
+ i++;
+ if (strncmp(text, cmd.name, strlen(text)) == 0) {
+ return strdup(cmd.name);
+ }
+ }
+
+ return NULL;
}
int cli_main() {
char* input = NULL;
- rl_completion_entry_function = rl_completion_entries;
+ rl_completion_entry_function = rl_completion_entries;
while (1) {
if (input != NULL) free(input);
@@ -73,9 +78,7 @@ int cli_main() {
if (*input == '\0') continue; // ignore empty lines
add_history(input);
- if (cli_cmd(input)) continue;
-
- printf("unknown command!\n");
+ cli_cmd(input);
}
return EXIT_SUCCESS;