summaryrefslogtreecommitdiff
path: root/demo/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'demo/util.c')
-rw-r--r--demo/util.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/demo/util.c b/demo/util.c
new file mode 100644
index 0000000..d08ec20
--- /dev/null
+++ b/demo/util.c
@@ -0,0 +1,157 @@
+#include <stddef.h>
+
+#include "demo.h"
+
+static void bad_input(void)
+{
+ print("bad input");
+}
+
+static void unexpected_eof(void)
+{
+ print("unexpected end-of-input");
+}
+
+static int parse_cpu_token(const char *token, unsigned *cpu)
+{
+ if (token[0] != 'c' || token[1] != 'p' || token[2] != 'u'
+ || !('0' <= token[3] && token[3] < '0' + NUM_CPUS) || token[4]) {
+ bad_input();
+ return -1;
+ }
+
+ *cpu = token[3] - '0';
+ return 0;
+}
+
+int strcmp(const char *s1, const char *s2)
+{
+ while (*s1 && *s1 == *s2)
+ s1++, s2++;
+
+ return (int)*(const unsigned char *)s1 - (int)*(const unsigned char *)s2;
+}
+
+char *strtok_input(char **tokens)
+{
+ char *start = *tokens;
+ while (*start && *start == ' ')
+ ++start;
+
+ if (!*start) {
+ *tokens = start;
+ return NULL;
+ }
+
+ char *end = start + 1;
+ while (*end && *end != ' ')
+ ++end;
+
+ *tokens = *end ? end + 1 : end;
+ *end = '\0';
+
+ return start;
+}
+
+int parse_cpu(char **tokens, unsigned *cpu)
+{
+ char *token = strtok_input(tokens);
+ if (!token) {
+ unexpected_eof();
+ return -1;
+ }
+
+ return parse_cpu_token(token, cpu);
+}
+
+int parse_cpu_mask(char **tokens, unsigned *mask)
+{
+ *mask = 0;
+
+ char *token;
+ while ((token = strtok_input(tokens))) {
+ unsigned cpu;
+ if (parse_cpu_token(token, &cpu) < 0)
+ return -1;
+
+ *mask |= 1 << cpu;
+ }
+
+ if (!*mask) {
+ print("must specify at least one cpu");
+ return -1;
+ }
+
+ return 0;
+}
+
+int parse_hex(char **tokens, unsigned *val)
+{
+ char *token = strtok_input(tokens);
+ if (!token) {
+ unexpected_eof();
+ return -1;
+ } else if (token[0] != '0' || token[1] != 'x') {
+ bad_input();
+ return -1;
+ }
+
+ *val = 0;
+
+ char *c = &token[2];
+ unsigned nibbles = 0;
+
+ while (*c) {
+ *val <<= 4;
+
+ if ('0' <= *c && *c <= '9')
+ *val |= *c - '0';
+ else if ('a' <= *c && *c <= 'f')
+ *val |= *c - 'a' + 10;
+ else if ('A' <= *c && *c <= 'F')
+ *val |= *c - 'A' + 10;
+
+ ++c;
+ ++nibbles;
+ }
+
+ if (!nibbles || nibbles > 8) {
+ bad_input();
+ return -1;
+ }
+
+ return 0;
+}
+
+int parse_ptr(char **tokens, void **ptr)
+{
+ unsigned ptr_val;
+ if (parse_hex(tokens, &ptr_val) < 0)
+ return -1;
+
+ *ptr = (void *)ptr_val;
+ return 0;
+}
+
+int parse_aligned(char **tokens, void **ptr)
+{
+ if (parse_ptr(tokens, ptr) < 0)
+ return -1;
+ else if ((unsigned)*ptr & 0b11) {
+ print("unaligned address: %p", *ptr);
+ return -1;
+ }
+
+ return 0;
+}
+
+int expect_end(char **tokens)
+{
+ char *token = strtok_input(tokens);
+ if (token) {
+ print("too many arguments starting from '%s'", token);
+ return -1;
+ }
+
+ return 0;
+}