summaryrefslogtreecommitdiff
path: root/userland/minibox/utilities/ed.c
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2023-10-22 19:50:38 +0200
committerAnton Kling <anton@kling.gg>2023-10-22 19:50:38 +0200
commit4e09bca9e34c226b6d7e34b4fa11248405fd988e (patch)
tree80f156b7940d9d19971395f335530170c69516c7 /userland/minibox/utilities/ed.c
Move everything into a new repo.
Diffstat (limited to 'userland/minibox/utilities/ed.c')
-rw-r--r--userland/minibox/utilities/ed.c145
1 files changed, 145 insertions, 0 deletions
diff --git a/userland/minibox/utilities/ed.c b/userland/minibox/utilities/ed.c
new file mode 100644
index 0000000..53270dc
--- /dev/null
+++ b/userland/minibox/utilities/ed.c
@@ -0,0 +1,145 @@
+// ed - edit text
+// ed [-p string] [-s] [file]
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#define COMMAND_MODE 0
+#define INPUT_MODE 1
+
+int mode = COMMAND_MODE;
+
+FILE *fp = NULL;
+FILE *mem_fp = NULL;
+int line_number = 1;
+
+int getline(char *buffer, size_t s) {
+ (void)s;
+ int i = 0;
+ char c;
+ for (;; i++) {
+ int rc = read(0, &c, 1);
+ assert(rc > 0);
+ printf("%c", c);
+ buffer[i] = c;
+ if ('\n' == c)
+ break;
+ }
+ buffer[i] = '\0';
+ return i;
+}
+
+void goto_line(void) {
+ char c;
+ fseek(mem_fp, 0, SEEK_SET);
+ int line = 1;
+ if (1 != line_number) {
+ // Goto line
+ for (; fread(&c, 1, 1, mem_fp);) {
+ if ('\n' == c)
+ line++;
+ if (line == line_number)
+ return;
+ }
+ printf("got to line: %d\n", line);
+ assert(0);
+ }
+}
+
+void read_line(void) {
+ char c;
+ goto_line();
+ for (; fread(&c, 1, 1, mem_fp);) {
+ if ('\n' == c)
+ break;
+ printf("%c", c);
+ }
+ printf("\n");
+}
+
+void goto_end_of_line(void) {
+ char c;
+ for (; fread(&c, 1, 1, mem_fp);) {
+ if ('\n' == c)
+ break;
+ }
+}
+
+void delete_line(void) {
+ long s = ftell(mem_fp);
+ printf("s: %d\n", s);
+ goto_end_of_line();
+ long end = ftell(mem_fp);
+ printf("end: %d\n", end);
+ long offset = end - s;
+ for (char buffer[4096];;) {
+ int rc = fread(buffer, 1, 100, mem_fp);
+ long reset = ftell(mem_fp);
+ if (0 == rc)
+ break;
+ fseek(mem_fp, s, SEEK_SET);
+ fwrite(buffer, 1, rc, mem_fp);
+ s += rc;
+ fseek(mem_fp, reset, SEEK_SET);
+ }
+}
+
+void read_command(void) {
+ char buffer[4096];
+ char *s = buffer;
+ getline(buffer, 4096);
+ int a = -1;
+ int rc = sscanf(buffer, "%d", &a);
+ if (0 < rc) {
+ line_number = a;
+ }
+ for (; isdigit(*s); s++)
+ ;
+ if (0 == strcmp(s, "i")) {
+ mode = INPUT_MODE;
+ return;
+ }
+ if (0 == strcmp(s, ".")) {
+ read_line();
+ return;
+ }
+ return;
+}
+
+void read_input(void) {
+ char buffer[4096];
+ int l = getline(buffer, 4096);
+ if (0 == strcmp(buffer, ".")) {
+ mode = COMMAND_MODE;
+ return;
+ }
+ goto_line();
+ delete_line();
+ goto_line();
+ assert(fwrite(buffer, l, 1, mem_fp));
+ return;
+}
+
+int ed_main(char argc, char **argv) {
+ if (argc < 2)
+ return 1;
+ char *buffer;
+ size_t size;
+ mem_fp = open_memstream(&buffer, &size);
+ assert(mem_fp);
+ fp = fopen(argv[1], "r");
+ assert(fp);
+ char r_buffer[4096];
+ for (int rc; (rc = fread(buffer, 1, 4096, fp));) {
+ fwrite(r_buffer, 1, rc, mem_fp);
+ }
+
+ for (;;) {
+ if (COMMAND_MODE == mode)
+ read_command();
+ else
+ read_input();
+ }
+ fclose(fp);
+ fclose(mem_fp);
+ return 0;
+}