summaryrefslogtreecommitdiff
path: root/userland
diff options
context:
space:
mode:
authorAnton Kling <anton@kling.gg>2024-04-11 17:22:00 +0200
committerAnton Kling <anton@kling.gg>2024-04-11 17:23:39 +0200
commitca082f686fd2dc7ee6f0284421f6212d6d4acee8 (patch)
tree493b1047661174816f0d1d300952e40e2846b24b /userland
parente25a47fcc4db09ab9b845a691297da67243e6049 (diff)
bug fixes
Diffstat (limited to 'userland')
-rw-r--r--userland/libc/Makefile2
-rw-r--r--userland/libc/assert.c6
-rw-r--r--userland/libc/dirent/scandir.c15
-rw-r--r--userland/libc/include/tb/sb.h23
-rw-r--r--userland/libc/include/tb/sv.h32
-rw-r--r--userland/libc/malloc/malloc.c56
-rw-r--r--userland/libc/stdio/vfprintf.c3
-rw-r--r--userland/libc/stdlib/realpath.c104
-rw-r--r--userland/libc/tb/sb.c69
-rw-r--r--userland/libc/tb/sv.c147
-rw-r--r--userland/libgui/libgui.c14
-rw-r--r--userland/terminal/term.c23
12 files changed, 408 insertions, 86 deletions
diff --git a/userland/libc/Makefile b/userland/libc/Makefile
index b1291fa..29b37d9 100644
--- a/userland/libc/Makefile
+++ b/userland/libc/Makefile
@@ -3,7 +3,7 @@ AR="i686-sb-ar"
AS="i686-sb-as"
#CFLAGS = -ggdb -ffreestanding -O2 -Wall -Wextra -pedantic -Wimplicit-fallthrough -I./include/ -static -I../../include/ -Wno-int-conversion -Wno-unused-parameter -Wno-return-type
CFLAGS = -ggdb -ffreestanding -Wall -Wextra -pedantic -Wimplicit-fallthrough -I./include/ -static -I../../include/ -Wno-int-conversion -Wno-unused-parameter -Wno-return-type
-OBJ=crt0.o libc.o malloc/malloc.o pty.o sys/mman/mmap.o sys/mman/munmap.o memset.o assert.o stdio/snprintf.o stdio/vfprintf.o string/memcpy.o string/memcmp.o string/strcmp.o ubsan.o string/strcpy.o isspace.o stdio/puts.o stdio/putchar.o dirent/opendir.o dirent/readdir.o dirent/closedir.o unistd/getopt.o dirent/scandir.o dirent/alphasort.o stdio/printf.o stdio/vdprintf.o stdio/vprintf.o stdio/dprintf.o stdio/vprintf.o string/strlen.o string/strnlen.o stdio/stdin.o stdio/getchar.o stdio/fgetc.o arpa/inet/htons.o arpa/inet/htonl.o stdio/fread.o stdio/fwrite.o stdio/fopen.o stdio/fclose.o stdio/fseek.o ctype/isascii.o stdio/fprintf.o stdlib/atoi.o stdlib/strtol.o ctype/toupper.o ctype/tolower.o string/strcat.o string/strchr.o string/sscanf.o sys/stat/stat.o stdlib/getenv.o string/strrchr.o stdio/ftell.o stdio/tmpfile.o stdio/fgets.o stdio/feof.o stdio/fscanf.o stdio/ungetc.o string/strncmp.o stdio/fputc.o string/strncpy.o stdio/remove.o stdio/ferror.o stdio/fputs.o stdlib/rand.o stdlib/srand.o unistd/getpid.o stdlib/strtoul.o stdio/fflush.o stdlib/abort.o string/strcspn.o time/localtime.o time/time.o time/clock_gettime.o time/gmtime.o time/strftime.o string/strpbrk.o ctype/isdigit.o ctype/isalpha.o ctype/isxdigit.o ctype/ispunct.o stdio/setvbuf.o stdio/fileno.o stdio/putc.o stdio/sprintf.o stdlib/abs.o string/strspn.o stdlib/qsort.o string/memmove.o setjmp/longjmp.o setjmp/setjmp.o libgen/basename.o string/strdup.o string/strndup.o string/strlcpy.o stdlib/atexit.o stdio/open_memstream.o libgen/dirname.o unistd/unlink.o string/strstr.o string/strcasecmp.o string/strncasecmp.o stdlib/mkstemp.o string/strtok.o unistd/execvp.o unistd/_exit.o ctype/isalnum.o time/ctime_r.o stdlib/strtold.o sys/time/gettimeofday.o stdio/fgetpos.o stdio/fsetpos.o ctype/isprint.o stdlib/system.o stdio/tmpnam.o unistd/msleep.o stdlib/atof.o stdlib/strtod.o stdio/rename.o sys/stat/mkdir.o unistd/uptime.o unistd/ftruncate.o sys/socket/recvfrom.o sys/socket/sendto.o signal/kill.o signal/sigaction.o unistd/chdir.o unistd/getcwd.o stdio/getdelim.o stdio/getline.o unistd/isatty.o sys/socket/listen.o stdlib/realpath.o systemcall.o sys/random/randomfill.o fcntl/open.o unistd/write.o unistd/pwrite.o fcntl/open_process.o
+OBJ=crt0.o libc.o malloc/malloc.o pty.o sys/mman/mmap.o sys/mman/munmap.o memset.o assert.o stdio/snprintf.o stdio/vfprintf.o string/memcpy.o string/memcmp.o string/strcmp.o ubsan.o string/strcpy.o isspace.o stdio/puts.o stdio/putchar.o dirent/opendir.o dirent/readdir.o dirent/closedir.o unistd/getopt.o dirent/scandir.o dirent/alphasort.o stdio/printf.o stdio/vdprintf.o stdio/vprintf.o stdio/dprintf.o stdio/vprintf.o string/strlen.o string/strnlen.o stdio/stdin.o stdio/getchar.o stdio/fgetc.o arpa/inet/htons.o arpa/inet/htonl.o stdio/fread.o stdio/fwrite.o stdio/fopen.o stdio/fclose.o stdio/fseek.o ctype/isascii.o stdio/fprintf.o stdlib/atoi.o stdlib/strtol.o ctype/toupper.o ctype/tolower.o string/strcat.o string/strchr.o string/sscanf.o sys/stat/stat.o stdlib/getenv.o string/strrchr.o stdio/ftell.o stdio/tmpfile.o stdio/fgets.o stdio/feof.o stdio/fscanf.o stdio/ungetc.o string/strncmp.o stdio/fputc.o string/strncpy.o stdio/remove.o stdio/ferror.o stdio/fputs.o stdlib/rand.o stdlib/srand.o unistd/getpid.o stdlib/strtoul.o stdio/fflush.o stdlib/abort.o string/strcspn.o time/localtime.o time/time.o time/clock_gettime.o time/gmtime.o time/strftime.o string/strpbrk.o ctype/isdigit.o ctype/isalpha.o ctype/isxdigit.o ctype/ispunct.o stdio/setvbuf.o stdio/fileno.o stdio/putc.o stdio/sprintf.o stdlib/abs.o string/strspn.o stdlib/qsort.o string/memmove.o setjmp/longjmp.o setjmp/setjmp.o libgen/basename.o string/strdup.o string/strndup.o string/strlcpy.o stdlib/atexit.o stdio/open_memstream.o libgen/dirname.o unistd/unlink.o string/strstr.o string/strcasecmp.o string/strncasecmp.o stdlib/mkstemp.o string/strtok.o unistd/execvp.o unistd/_exit.o ctype/isalnum.o time/ctime_r.o stdlib/strtold.o sys/time/gettimeofday.o stdio/fgetpos.o stdio/fsetpos.o ctype/isprint.o stdlib/system.o stdio/tmpnam.o unistd/msleep.o stdlib/atof.o stdlib/strtod.o stdio/rename.o sys/stat/mkdir.o unistd/uptime.o unistd/ftruncate.o sys/socket/recvfrom.o sys/socket/sendto.o signal/kill.o signal/sigaction.o unistd/chdir.o unistd/getcwd.o stdio/getdelim.o stdio/getline.o unistd/isatty.o sys/socket/listen.o stdlib/realpath.o systemcall.o sys/random/randomfill.o fcntl/open.o unistd/write.o unistd/pwrite.o fcntl/open_process.o tb/sb.o tb/sv.o
all: libc.a
%.o: %.c
diff --git a/userland/libc/assert.c b/userland/libc/assert.c
index 4082f64..6a3bd6e 100644
--- a/userland/libc/assert.c
+++ b/userland/libc/assert.c
@@ -2,8 +2,10 @@
#include <stdio.h>
#include <stdlib.h>
+int debug_printf(const char *fmt, ...);
+
void aFailed(char *f, int l) {
- printf("Assert failed\n");
- printf("%s : %d\n", f, l);
+ debug_printf("Assert failed\n");
+ debug_printf("%s : %d\n", f, l);
exit(1);
}
diff --git a/userland/libc/dirent/scandir.c b/userland/libc/dirent/scandir.c
index 945bc1f..564cbc8 100644
--- a/userland/libc/dirent/scandir.c
+++ b/userland/libc/dirent/scandir.c
@@ -2,11 +2,6 @@
#include <stdlib.h>
#include <string.h>
-int nop_sel(const struct dirent *unused) {
- (void)unused;
- return 1;
-}
-
int nop_compar(const struct dirent **d1, const struct dirent **d2) {
*d2 = *d1;
return 0;
@@ -15,9 +10,6 @@ int nop_compar(const struct dirent **d1, const struct dirent **d2) {
int scandir(const char *dir, struct dirent ***namelist,
int (*sel)(const struct dirent *),
int (*compar)(const struct dirent **, const struct dirent **)) {
- if (!sel)
- sel = nop_sel;
-
if (!compar)
compar = nop_compar;
@@ -28,8 +20,11 @@ int scandir(const char *dir, struct dirent ***namelist,
struct dirent *e;
int rc = 0;
for (; (e = readdir(d));) {
- if (!sel(e))
- continue;
+ if (sel) {
+ if (!sel(e)) {
+ continue;
+ }
+ }
struct dirent *p = malloc(sizeof(struct dirent));
memcpy(p, e, sizeof(struct dirent));
list = realloc(list, (rc + 1) * sizeof(struct dirent *));
diff --git a/userland/libc/include/tb/sb.h b/userland/libc/include/tb/sb.h
new file mode 100644
index 0000000..5675985
--- /dev/null
+++ b/userland/libc/include/tb/sb.h
@@ -0,0 +1,23 @@
+#ifndef SB_H
+#define SB_H
+#include "sv.h"
+#include <stddef.h>
+
+struct sb {
+ char *string;
+ size_t length;
+ size_t capacity;
+};
+
+struct sv;
+
+void sb_init(struct sb *ctx);
+void sb_free(struct sb *ctx);
+void sb_reset(struct sb *ctx);
+int sb_isempty(const struct sb *ctx);
+void sb_append_char(struct sb *ctx, char c);
+int sb_delete_right(struct sb *ctx, int n);
+void sb_append(struct sb *ctx, const char *s);
+void sb_append_sv(struct sb *ctx, struct sv sv);
+void sb_prepend_sv(struct sb *ctx, struct sv sv);
+#endif
diff --git a/userland/libc/include/tb/sv.h b/userland/libc/include/tb/sv.h
new file mode 100644
index 0000000..6e81b0b
--- /dev/null
+++ b/userland/libc/include/tb/sv.h
@@ -0,0 +1,32 @@
+#ifndef SV_H
+#define SV_H
+#include "sb.h"
+#include <stddef.h>
+
+#define SB_TO_SV(_sb) \
+ (struct sv) { \
+ .s = (_sb).string, .length = (_sb).length \
+ }
+
+#define C_TO_SV(_c_string) \
+ ((struct sv){.length = strlen(_c_string), .s = (_c_string)})
+
+struct sv {
+ const char *s;
+ size_t length;
+};
+
+char *SV_TO_C(struct sv s);
+struct sv sv_split_delim(const struct sv input, struct sv *rest, char delim);
+struct sv sv_end_split_delim(const struct sv input, struct sv *rest,
+ char delim);
+struct sv sv_split_space(const struct sv input, struct sv *rest);
+int sv_isempty(struct sv s);
+char sv_peek(struct sv s);
+int sv_eq(struct sv a, struct sv b);
+int sv_partial_eq(struct sv a, struct sv b);
+struct sv sv_trim_left(struct sv s, size_t n);
+struct sv sv_clone(struct sv s);
+struct sv sv_clone_from_c(const char *s);
+char *sv_copy_to_c(struct sv s, char *out, size_t buffer_length);
+#endif
diff --git a/userland/libc/malloc/malloc.c b/userland/libc/malloc/malloc.c
index d1bc5ca..1c992ef 100644
--- a/userland/libc/malloc/malloc.c
+++ b/userland/libc/malloc/malloc.c
@@ -1,5 +1,6 @@
#include <assert.h>
#include <math.h>
+#include <stdarg.h>
#include <stddef.h>
#include <stdlib.h>
#include <typedefs.h>
@@ -23,6 +24,26 @@ MallocHeader *head = NULL;
MallocHeader *final = NULL;
u32 total_heap_size = 0;
+// printf without using malloc() so that it can be used internally by
+// malloc() such that it does not have a stack overflow.
+int debug_vprintf(const char *fmt, va_list ap) {
+ const char buffer[4096];
+ int rc = vsnprintf(buffer, 4096, fmt, ap);
+ if (0 > rc) {
+ return -1;
+ }
+ write(1, buffer, rc);
+ return rc;
+}
+
+int debug_printf(const char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ int rc = debug_vprintf(fmt, ap);
+ va_end(ap);
+ return rc;
+}
+
int init_heap(void) {
head = (MallocHeader *)sbrk(NEW_ALLOC_SIZE);
total_heap_size += NEW_ALLOC_SIZE - sizeof(MallocHeader);
@@ -63,8 +84,10 @@ MallocHeader *next_header(MallocHeader *a) {
assert(a->magic == 0xdde51ab9410268b1);
if (a->n) {
if (a->n->magic != 0xdde51ab9410268b1) {
- printf("Real magic value is: %x\n", a->n->magic);
- printf("location: %x\n", &(a->n->magic));
+ debug_printf("a->n: %x\n", a->n);
+ debug_printf("Real magic value is: %x\n", a->n->magic);
+ debug_printf("size: %x\n", a->n->size);
+ debug_printf("location: %x\n", &(a->n->magic));
assert(0);
}
return a->n;
@@ -74,7 +97,7 @@ MallocHeader *next_header(MallocHeader *a) {
MallocHeader *next_close_header(MallocHeader *a) {
if (!a) {
- printf("next close header fail\n");
+ debug_printf("next close header fail\n");
for (;;)
;
}
@@ -122,13 +145,16 @@ void merge_headers(MallocHeader *b) {
b->size += n->size;
b->flags |= n->flags & IS_FINAL;
b->n = n->n;
+ assert(b->magic == 0xdde51ab9410268b1);
+ if (b->n) {
+ assert(b->n->magic == 0xdde51ab9410268b1);
+ }
if (n == final) {
final = b;
}
}
-void *malloc(size_t s) {
- s += 0x1000;
+void *int_malloc(size_t s, int recursion) {
size_t n = s;
MallocHeader *free_entry = find_free_entry(s);
if (!free_entry) {
@@ -136,7 +162,11 @@ void *malloc(size_t s) {
assert(0);
return NULL;
}
- return malloc(s);
+ if (recursion) {
+ debug_printf("RECURSION IN MALLOC :(\n");
+ assert(0);
+ }
+ return int_malloc(s, 1);
}
void *rc = (void *)(free_entry + 1);
@@ -158,12 +188,14 @@ void *malloc(size_t s) {
free_entry->flags = 0;
free_entry->n = new_entry;
free_entry->magic = 0xdde51ab9410268b1;
- for (int i = 0; i < s; i++) {
- *(char *)rc = 'A';
- }
+ randomfill(rc, s);
return rc;
}
+void *malloc(size_t s) {
+ return int_malloc(s, 0);
+}
+
size_t get_mem_size(void *ptr) {
if (!ptr) {
return 0;
@@ -216,13 +248,9 @@ void free(void *p) {
if (!p) {
return;
}
- // FIXME: This assumes that p is at the start of a allocated area.
- // Could this be avoided in a simple way?
MallocHeader *h = (MallocHeader *)((uintptr_t)p - sizeof(MallocHeader));
assert(h->magic == 0xdde51ab9410268b1);
- if (h->flags & IS_FREE) {
- return;
- }
+ assert(!(h->flags & IS_FREE));
h->flags |= IS_FREE;
merge_headers(h);
diff --git a/userland/libc/stdio/vfprintf.c b/userland/libc/stdio/vfprintf.c
index c3a8de7..65a2c27 100644
--- a/userland/libc/stdio/vfprintf.c
+++ b/userland/libc/stdio/vfprintf.c
@@ -93,9 +93,8 @@ int print_string(FILE *f, const char *s, int *rc, int prefix, int right_padding,
break;
bl--;
}
- int r;
+ int r = 0;
FILE_WRITE(f, (const unsigned char *)s, 1, &r);
- assert(r != 0);
}
if (right_padding) {
assert(-1 == precision); // FIXME: Is this correct?
diff --git a/userland/libc/stdlib/realpath.c b/userland/libc/stdlib/realpath.c
index 5589032..d9e2387 100644
--- a/userland/libc/stdlib/realpath.c
+++ b/userland/libc/stdlib/realpath.c
@@ -1,62 +1,68 @@
#include <assert.h>
+#include <errno.h>
#include <stdlib.h>
#include <string.h>
+#include <tb/sb.h>
+#include <tb/sv.h>
#include <unistd.h>
-// FIXME: This is nowhere near complete
char *realpath(const char *filename, char *resolvedname) {
- assert(resolvedname);
- // FIXME: This really should have bounds checking
+ if (!filename) {
+ return -EINVAL;
+ }
+
char cwd[256];
getcwd(cwd, 256);
- strcat(cwd, filename);
- const char *path = cwd;
- char *result = resolvedname;
- // It has to be a absolute path
- if ('/' != *path)
- return 0;
- const char *result_start = result;
- int start_directory = 0;
- int should_insert_slash = 0;
- for (; *path; path++) {
- if (start_directory) {
- start_directory = 0;
- if ('/' == *path) {
- path++;
- } else if (0 == memcmp(path, "./", 2) || 0 == memcmp(path, ".\0", 2)) {
- path++;
- } else if (0 == memcmp(path, "../", 3) || 0 == memcmp(path, "..\0", 3)) {
- path += 2;
- if (result_start + 2 > result) {
- // The path is probably something like "/.." or
- // "/../foo". A "/.." should become a "/"
- // Therefore it skips going back to the parent
- if (*path == '/') {
- if (result_start == result)
- return 0;
- result--;
- }
- } else {
- if ('/' != *path) {
- should_insert_slash = 1;
- }
- result--;
- result--;
- for (; result_start <= result && '/' != *result; result--)
- ;
- }
+ strcat(cwd, filename); // FIXME: bounds check
+
+ struct sb string;
+ sb_init(&string);
+
+ struct sv path = C_TO_SV(cwd);
+
+ int ignore = 0;
+ int last_was_dotdot = 0;
+
+ int was_root = 0;
+ for (;;) {
+ ignore = 0;
+ was_root = 0;
+ struct sv dir = sv_end_split_delim(path, &path, '/');
+
+ if (sv_partial_eq(dir, C_TO_SV("/"))) {
+ was_root = 1;
+ }
+
+ if (sv_eq(dir, C_TO_SV("/"))) {
+ ignore = 1;
+ }
+
+ if (sv_eq(dir, C_TO_SV("/."))) {
+ ignore = 1;
+ }
+
+ if (sv_eq(dir, C_TO_SV("/.."))) {
+ last_was_dotdot = 1;
+ ignore = 1;
+ } else {
+ if (last_was_dotdot) {
+ ignore = 1;
}
+ last_was_dotdot = 0;
+ }
+
+ if (!ignore && !last_was_dotdot) {
+ sb_prepend_sv(&string, dir);
}
- start_directory = ('/' == *path);
- if ('\0' == *path)
+
+ if (sv_isempty(path)) {
+ if (was_root && ignore && sb_isempty(&string)) {
+ sb_prepend_sv(&string, C_TO_SV("/"));
+ }
break;
- *result = *path;
- result++;
- }
- if (should_insert_slash) {
- *result = '/';
- result++;
+ }
}
- *result = '\0';
- return 1;
+ char *result = sv_copy_to_c(SB_TO_SV(string), resolvedname, 256);
+ sb_free(&string);
+ return result;
}
diff --git a/userland/libc/tb/sb.c b/userland/libc/tb/sb.c
new file mode 100644
index 0000000..0d0ec52
--- /dev/null
+++ b/userland/libc/tb/sb.c
@@ -0,0 +1,69 @@
+#include <tb/sb.h>
+#include <math.h>
+#include <stdlib.h>
+#include <string.h>
+
+void sb_init(struct sb *ctx) {
+ ctx->string = malloc(512);
+ ctx->length = 0;
+ ctx->capacity = 512;
+}
+
+void sb_free(struct sb *ctx) {
+ ctx->length = 0;
+ ctx->capacity = 0;
+ free(ctx->string);
+ ctx->string = NULL;
+}
+
+void sb_reset(struct sb *ctx) {
+ ctx->length = 0;
+}
+
+int sb_isempty(const struct sb *ctx) {
+ return (0 == ctx->length);
+}
+
+void sb_append_char(struct sb *ctx, char c) {
+ if (1 > ctx->capacity - ctx->length) {
+ ctx->capacity += 32;
+ ctx->string = realloc(ctx->string, ctx->capacity);
+ }
+ memcpy(ctx->string + ctx->length, &c, 1);
+ ctx->length++;
+}
+
+int sb_delete_right(struct sb *ctx, int n) {
+ n = min(n, ctx->length);
+ ctx->length -= n;
+ return n;
+}
+
+void sb_append(struct sb *ctx, const char *s) {
+ size_t l = strlen(s);
+ if (l > ctx->capacity - ctx->length) {
+ ctx->capacity += l;
+ ctx->string = realloc(ctx->string, ctx->capacity);
+ }
+ memcpy(ctx->string + ctx->length, s, l);
+ ctx->length += l;
+}
+
+void sb_prepend_sv(struct sb *ctx, struct sv sv) {
+ if (sv.length > ctx->capacity - ctx->length) {
+ ctx->capacity += sv.length;
+ ctx->string = realloc(ctx->string, ctx->capacity);
+ }
+ memmove(ctx->string + sv.length, ctx->string, ctx->length);
+ memcpy(ctx->string, sv.s, sv.length);
+ ctx->length += sv.length;
+}
+
+void sb_append_sv(struct sb *ctx, struct sv sv) {
+ if (sv.length > ctx->capacity - ctx->length) {
+ ctx->capacity += sv.length;
+ ctx->string = realloc(ctx->string, ctx->capacity);
+ }
+ memcpy(ctx->string + ctx->length, sv.s, sv.length);
+ ctx->length += sv.length;
+}
diff --git a/userland/libc/tb/sv.c b/userland/libc/tb/sv.c
new file mode 100644
index 0000000..9bffce3
--- /dev/null
+++ b/userland/libc/tb/sv.c
@@ -0,0 +1,147 @@
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tb/sv.h>
+
+char *SV_TO_C(struct sv s) {
+ char *c_string = malloc(s.length + 1);
+ memcpy(c_string, s.s, s.length);
+ c_string[s.length] = '\0';
+ return c_string;
+}
+
+struct sv sv_split_space(const struct sv input, struct sv *rest) {
+ struct sv r = {
+ .s = input.s,
+ };
+ for (size_t i = 0; i < input.length; i++) {
+ if (isspace(input.s[i])) {
+ r.length = i;
+ if (rest) {
+ rest->s += i + 1;
+ rest->length -= (i + 1);
+ }
+ return r;
+ }
+ }
+
+ if (rest) {
+ rest->s = NULL;
+ rest->length = 0;
+ }
+ return input;
+}
+
+struct sv sv_end_split_delim(const struct sv input, struct sv *rest,
+ char delim) {
+ for (size_t i = input.length - 1; i > 0; i--) {
+ if (delim == input.s[i]) {
+ struct sv r = {
+ .s = (input.s + i),
+ .length = input.length - i,
+ };
+ if (rest) {
+ rest->s = input.s;
+ rest->length = i;
+ }
+ return r;
+ }
+ }
+
+ if (rest) {
+ rest->s = NULL;
+ rest->length = 0;
+ }
+ return input;
+}
+
+struct sv sv_split_delim(const struct sv input, struct sv *rest, char delim) {
+ struct sv r = {
+ .s = input.s,
+ };
+ for (size_t i = 0; i < input.length; i++) {
+ if (delim == input.s[i]) {
+ r.length = i;
+ if (rest) {
+ rest->s += i + 1;
+ rest->length -= (i + 1);
+ }
+ return r;
+ }
+ }
+
+ if (rest) {
+ rest->s = NULL;
+ rest->length = 0;
+ }
+ return input;
+}
+
+int sv_isempty(struct sv s) {
+ return (0 == s.length);
+}
+
+char sv_peek(struct sv s) {
+ if (0 == s.length) {
+ return '\0';
+ }
+ return s.s[0];
+}
+
+int sv_partial_eq(struct sv a, struct sv b) {
+ if (a.length < b.length) {
+ return 0;
+ }
+ for (size_t i = 0; i < b.length; i++) {
+ if (a.s[i] != b.s[i]) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+int sv_eq(struct sv a, struct sv b) {
+ if (a.length != b.length) {
+ return 0;
+ }
+ for (size_t i = 0; i < a.length; i++) {
+ if (a.s[i] != b.s[i]) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+struct sv sv_trim_left(struct sv s, size_t n) {
+ if (s.length < n) {
+ s.s += s.length;
+ s.length = 0;
+ return s;
+ }
+ s.s += n;
+ s.length -= n;
+ return s;
+}
+
+struct sv sv_clone(struct sv s) {
+ struct sv new_sv;
+ new_sv.length = s.length;
+ char *new_string = malloc(s.length);
+ memcpy(new_string, s.s, s.length);
+ new_sv.s = new_string;
+ return new_sv;
+}
+
+char *sv_copy_to_c(struct sv s, char *out, size_t buffer_length) {
+ int copy_len = min(s.length + 1, buffer_length);
+ if (!out) {
+ out = malloc(copy_len);
+ }
+ memcpy(out, s.s, copy_len - 1);
+ out[copy_len] = '\0';
+ return out;
+}
+
+struct sv sv_clone_from_c(const char *s) {
+ return sv_clone(C_TO_SV(s));
+}
diff --git a/userland/libgui/libgui.c b/userland/libgui/libgui.c
index 2a8361d..f7a8079 100644
--- a/userland/libgui/libgui.c
+++ b/userland/libgui/libgui.c
@@ -256,8 +256,15 @@ void GUI_EventLoop(GUI_Window *w, void (*event_handler)(WS_EVENT ev)) {
}
}
+// This should really not be a constant. It is merely here so that each
+// window can be given a sufficently large buffer such that buffers
+// don't have to be resized if the window is resized.
+#define MAX_WINDOW_SIZE (1920 * 1080)
void GUI_Resize(GUI_Window *w, uint32_t sx, uint32_t sy) {
- ftruncate(w->bitmap_fd, sx * sy * sizeof(uint32_t));
+ if (sx * sy > MAX_WINDOW_SIZE) {
+ return;
+ }
+
w->sx = sx;
w->sy = sy;
char buffer[sizeof(uint8_t) + sizeof(uint32_t) * 2];
@@ -298,8 +305,9 @@ GUI_Window *GUI_CreateWindow(uint32_t x, uint32_t y, uint32_t sx, uint32_t sy) {
printf("bitmap_fd: %x\n", w->bitmap_fd);
assert(0);
}
- ftruncate(w->bitmap_fd, sx * sy * sizeof(uint32_t));
- void *rc = mmap(NULL, sx * sy * sizeof(uint32_t), 0, 0, w->bitmap_fd, 0);
+ ftruncate(w->bitmap_fd, MAX_WINDOW_SIZE * sizeof(uint32_t));
+ void *rc =
+ mmap(NULL, MAX_WINDOW_SIZE * sizeof(uint32_t), 0, 0, w->bitmap_fd, 0);
if (!((int)rc >= 0)) {
printf("rc: %x\n", rc);
assert(0);
diff --git a/userland/terminal/term.c b/userland/terminal/term.c
index cd75a90..b0eabfd 100644
--- a/userland/terminal/term.c
+++ b/userland/terminal/term.c
@@ -14,6 +14,8 @@
#define TERM_BACKGROUND 0x000000
+char terminal_char_buffer[1920 / 8][1080 / 8] = {0};
+
int cmdfd;
GUI_Window *global_w;
uint32_t screen_pos_x = 0;
@@ -25,7 +27,7 @@ int shell_pid;
int raw_mode = 0;
void execsh(void) {
- char *argv[] = {NULL};
+ char *argv[] = {"/sh", NULL};
execv("/sh", argv);
}
@@ -45,6 +47,7 @@ void screen_update_cursor() {
void screen_putchar(uint32_t c) {
if (raw_mode) {
GUI_DrawFont(global_w, screen_pos_x, screen_pos_y, c);
+ terminal_char_buffer[screen_pos_y / 8][screen_pos_x / 8] = c;
screen_remove_old_cursor();
return;
}
@@ -70,6 +73,7 @@ void screen_putchar(uint32_t c) {
screen_pos_y -= 8;
}
GUI_DrawFont(global_w, screen_pos_x, screen_pos_y, c);
+ terminal_char_buffer[screen_pos_y / 8][screen_pos_x / 8] = c;
screen_pos_x += 8;
if (screen_pos_x >= global_w->sx - 8) {
screen_pos_x = 0;
@@ -223,6 +227,15 @@ void handle_escape_codes_or_print(char *buffer, int len) {
handle_escape_codes_or_print(buffer, len);
}
+void terminal_resize(uint32_t sx, uint32_t sy) {
+ GUI_Resize(global_w, sx, sy);
+ for (int y = 0; y < sy; y += 8) {
+ for (int x = 0; x < sx; x += 8) {
+ GUI_DrawFont(global_w, x, y, terminal_char_buffer[y / 8][x / 8]);
+ }
+ }
+}
+
void run() {
char buffer[4096];
struct pollfd fds[2];
@@ -253,10 +266,10 @@ void run() {
exit(0);
return;
}
- // if (WINDOWSERVER_EVENT_WINDOW_RESIZE == e.type) {
- // GUI_Resize(global_w, e.vector[0], e.vector[1]);
- // continue;
- // }
+ if (WINDOWSERVER_EVENT_WINDOW_RESIZE == e.type) {
+ terminal_resize(e.vector[0], e.vector[1]);
+ continue;
+ }
if (WINDOWSERVER_EVENT_KEYPRESS != e.type) {
continue;
}