aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNathan Reiner <nathan@nathanreiner.xyz>2023-02-15 16:35:40 +0100
committerNathan Reiner <nathan@nathanreiner.xyz>2023-02-15 16:35:40 +0100
commit5ecb8aafa496e9dfff51378be50eb29858b5465a (patch)
tree312a64f45148d03464c08f309af4a9a46a3f4ec8
parent0d9c643920a9431870983c896fb0b45d87d88afe (diff)
add quote parsing to smash
-rw-r--r--lib/cstr/cstr.c35
-rw-r--r--lib/cstr/cstr.h1
-rw-r--r--smash/main.c4
-rw-r--r--smash/parser.c5
-rw-r--r--smash/prompt.c22
-rw-r--r--smash/prompt.h6
6 files changed, 69 insertions, 4 deletions
diff --git a/lib/cstr/cstr.c b/lib/cstr/cstr.c
index 9f4ad6f..e30a774 100644
--- a/lib/cstr/cstr.c
+++ b/lib/cstr/cstr.c
@@ -83,6 +83,41 @@ u64 cstr_split(char *cstr, char split)
return splits;
}
+/** DOC
+ * @type function
+ * @name cstr_split
+ *
+ * @param char *cstr
+ * @param char split
+ * @return u64
+ *
+ * @description
+ * Splits a string on every `split` char.
+ * Returns the number of splits.
+ * ``WARNING`` This function does replace all `split` char with `0`.
+ * The old string does not exist after calling this function.
+ */
+u64 cstr_split_with_cancel(char *cstr, char split, char cancel)
+{
+ u64 splits = 1;
+ u8 is_in_cancel = 0;
+
+ while (*cstr) {
+ if (*cstr == cancel) {
+ is_in_cancel = !is_in_cancel;
+ }
+
+ if (*cstr == split && !is_in_cancel) {
+ *cstr = 0;
+ ++splits;
+ }
+
+ ++cstr;
+ }
+
+ return splits;
+}
+
/** DOC
* @type function
diff --git a/lib/cstr/cstr.h b/lib/cstr/cstr.h
index ce27eb0..049c867 100644
--- a/lib/cstr/cstr.h
+++ b/lib/cstr/cstr.h
@@ -11,6 +11,7 @@ typedef struct {
u64 cstr_length(const char *);
i8 cstr_compare(const char *a, const char *b);
u64 cstr_split(char *cstr, char split);
+u64 cstr_split_with_cancel(char *cstr, char split, char cancel);
const char *next_split(const char *previous);
u64 strip_front(char *cstr, char strip);
u64 strip_back(char *cstr, char strip);
diff --git a/smash/main.c b/smash/main.c
index efc7bd1..3c5b559 100644
--- a/smash/main.c
+++ b/smash/main.c
@@ -2,6 +2,7 @@
#include "comment.h"
#include "env.h"
#include "variable.h"
+#include "prompt.h"
#include "../lib/sys/io.h"
#include "../lib/cstr/cstr.h"
@@ -15,7 +16,6 @@
int main(int argc, char *argv[])
{
- char prompt[] = "$ ";
i64 line_length;
int fd = STDIN_FD;
char linebuf[BUFSIZ];
@@ -35,7 +35,7 @@ int main(int argc, char *argv[])
while (1) {
if (fd == STDIN_FD)
- wstd(prompt);
+ prompt();
line_length = get_next_line_from_fd(fd, linebuf);
diff --git a/smash/parser.c b/smash/parser.c
index 55a6fd2..a0ea9d8 100644
--- a/smash/parser.c
+++ b/smash/parser.c
@@ -11,7 +11,7 @@ void __free_argv(char **argv);
expression_list_t *new_expression_from_line(char *line)
{
- u64 n = cstr_split(line, '|');
+ u64 n = cstr_split_with_cancel(line, '|', '"');
char *current = line;
char *next = 0;
expression_list_t *head = 0;
@@ -54,7 +54,7 @@ void free_expression(expression_list_t *expression)
char **new_argv(char *exp)
{
- u64 n = cstr_split(exp, ' ');
+ u64 n = cstr_split_with_cancel(exp, ' ', '"');
char **argv = malloc(sizeof(char*) * (n + 1));
u64 i = 0;
char *current = exp;
@@ -65,6 +65,7 @@ char **new_argv(char *exp)
for (; n > 0; --n) {
next = (char*)next_split(current);
strip_cstr(current, ' ');
+ strip_cstr(current, '"');
if (cstr_length(current))
argv[i++] = current;
diff --git a/smash/prompt.c b/smash/prompt.c
new file mode 100644
index 0000000..3b6b3c2
--- /dev/null
+++ b/smash/prompt.c
@@ -0,0 +1,22 @@
+#include "prompt.h"
+
+#include "../lib/sys/execve.h"
+#include "../lib/sys/wait4.h"
+#include "../lib/sys/fork.h"
+#include "../lib/sys/exit.h"
+#include "../lib/env/env.h"
+#include "../lib/io/io.h"
+
+void prompt()
+{
+ int pid = fork();
+
+ if (pid == 0) {
+ const char *argv[] = {"/system/config/smash.d/prompt", 0};
+ execve(argv[0], argv, getenvp());
+ wstd("> ");
+ exit(0);
+ }
+
+ wait4(pid, 0, 0, 0);
+}
diff --git a/smash/prompt.h b/smash/prompt.h
new file mode 100644
index 0000000..143a537
--- /dev/null
+++ b/smash/prompt.h
@@ -0,0 +1,6 @@
+#ifndef PROMPT_H
+#define PROMPT_H
+
+void prompt();
+
+#endif