wm: teppich

Download patch

ref: 377da78d28bcd0dcc90d963719eb6297ceeed13f
parent: bb4b8654acda0d7ec184206cf0ed186d6625ba6e
author: mkf <mkf@cloud9p.org>
date: Wed Nov 22 05:52:49 EST 2023

a few (gazillions) of changes

cons, pccons, bitcons: disable at compile time, too buggy to be of any use,
Makefile: make ld quiet about executable stack,
Makefile: add cmd/,
Makefile: add strcntok, strccnt,
cmd/echo: import a basic echo,
cmd/echo: add a bitmapped font option,
cmd/rc: add a basic shell,
include/u.h: add prog_t, used by rc.h,
include/libc.h, include/u.h: add some stdarg macros and va_list,
libc/lldel.c: free(!) deleted values,
libc/lladd: fixed a memory leak,
libc/strccnt.c: import (returns how many times a character have been found on a string),
libc/strcntok.c: import (returns nth time of token happening in src, kinda like strtok, but without states),
libc/strlen.c: small changes,
pc/com.c: delete com_getl(),
pc/boot.s: bump stack size to 32kb,
pc/kern.c get rid of (s)hell(-ish) codes, it now lives in cmd/rc,
pc/mem.c: fix a small mistake,
pc/vga.c: style updates,
include/cons.h: tidy up,

that's all.

--- a/Makefile
+++ b/Makefile
@@ -7,19 +7,25 @@
 
 CFLAGS +=-O0 -g -nostdinc -I./include/ -ffreestanding -fcommon -fno-pie
 ASFLAGS += -g
-LDFLAGS += -T linker.ld
+LDFLAGS += -T linker.ld -z noexecstack
 
 QEMU ?= qemu-system-i386
 QFLAGS +=-machine accel=kvm:tcg -m 2M -serial stdio -kernel teppich.elf
 
+C = \
+	cmd/rc.o\
+	cmd/echo.o\
+
 L = \
 	libc/strlen.o\
 	libc/strcmp.o\
+	libc/strcntok.o\
+	libc/strccnt.o\
 	libc/memcpy.o\
 	libc/memset.o\
-	libc/lladd.o \
+	libc/lladd.o\
 	libc/lldel.o\
-
+	
 K = \
 	pc/boot.o\
 	pc/x86.o\
@@ -28,9 +34,9 @@
 	pc/ps2.o\
 	pc/com.o\
 	pc/mem.o\
-	pc/cons.o\
 	pc/bitmap.o\
-	${L}
+	${L}\
+	${C}\
 
 all: teppich.elf
 
--- /dev/null
+++ b/cmd/echo.c
@@ -1,0 +1,29 @@
+#include <u.h>
+#include <libc.h>
+
+#include <vga.h>
+#include <bitmap.h>
+
+void
+echo_main(int argc, char **argv)
+{
+	int i;
+	void (*puts)(char*);
+	
+	puts = vga_puts;
+	i = 1;
+	if(argc >= 1 && !strcmp(argv[1], "-b"))
+	{
+		puts = bitputs;
+		i = 2;
+	}
+	
+	while(i < argc)
+	{
+		puts(argv[i]);
+		puts(" ");
+		i++;
+	}
+	
+	vga_putc('\n');
+}
--- /dev/null
+++ b/cmd/rc.c
@@ -1,0 +1,86 @@
+#include <u.h>
+#include <libc.h>
+
+#include <ps2.h>
+#include <vga.h>
+
+#include <mem.h>
+#include <err.h>
+#include "rc.h"
+
+int
+run(char *cmd)
+{
+	int argc;
+	char *arg0, **argv;
+	
+	/* always always always
+	check for nil pointers */
+	
+	arg0 = strcntok(cmd, ' ', 0);
+	
+	if(!arg0)
+	{
+		arg0 = cmd;
+		argc = 0;
+	}
+	else
+	{
+		for(argc = 0 ; argc < (strccnt(cmd, ' ') + 1) ; argc++)
+		{
+			argv[argc] = strcntok(cmd, ' ', argc);
+		}
+	}
+	for(int i = 0 ; i < sizeof(cmdtbl) ; i++)
+	{
+		if(!strcmp(arg0, cmdtbl[i].name))
+			return cmdtbl[i].main(argc, argv);
+	}
+	vga_puts("No such command\n");
+	
+	return NO_SUCH_CMD;
+}
+
+void
+rc_main(void)
+{
+	char c;
+	char *cmd;
+
+	int i = 0;
+	memset(cmd, 0, 25);
+	
+	vga_puts("> ");
+	while(1)
+	{
+		c = ps2_getc();
+		vga_putc(c);
+		
+		if(c == '\r' || c == '\n')
+		{
+			cmd[i] = '\0';
+			run(cmd);
+			
+			/* clear the mess */
+			cmd = malloc(25);
+			i = 0;
+			
+			vga_puts("> ");
+		}
+		/* ignore spaces as first character and ignore more than one space */
+		else if((c == ' ') && (i == 0 || cmd[i - 1] == ' '))
+			continue;
+		else if(c != '\b')
+		{
+			cmd[i] = c;
+			i++;
+		}
+		else
+		{
+			/* we don't want a negative i */
+			if(i)
+				i--;
+			cmd[i] = 0;
+		}
+	}
+}
--- /dev/null
+++ b/cmd/rc.h
@@ -1,0 +1,9 @@
+#pragma once
+
+int echo_main(int argc, char **argv);
+void rc_main(void);
+
+static prog_t cmdtbl[] =
+{
+	{"echo", echo_main},
+};
--- a/include/cons.h
+++ b/include/cons.h
@@ -11,9 +11,9 @@
 	void (*scroll)(int lines);
 }consdev_t;
 
-void consinit(consdev_t);
-void consclear(consdev_t, char);
-void conswrite(consdev_t cons, char* s);
-void consputc(consdev_t, char c);
+void consinit(consdev_t cons);
+void consclear(consdev_t cons, char c);
+void conswrite(consdev_t cons, char *s);
+void consputc(consdev_t cons, char c);
 char consread(consdev_t cons);
-void consscroll(consdev_t, int lines);
+void consscroll(consdev_t cons, int lines);
--- a/include/libc.h
+++ b/include/libc.h
@@ -1,8 +1,18 @@
 #pragma once
 
+#define va_start(ap, param)	__builtin_va_start(ap, param)
+#define va_end(ap)	__builtin_va_end(ap)
+#define va_arg(ap, type)	__builtin_va_arg(ap, type)
+
 int strlen(char *s);
 int strcmp(char *s1, char *s2);
+char* strtok(char *s, char *b);
+char* strcntok(char *src, char token, int n);
+int strccnt(char *s, char c);
+
 void* memset(void* src, char c, unsigned int len);
 void* memcpy(void *a1, void *a2, unsigned int len);
+
 int lladd(ll_t*, void*);
 int lldel(ll_t*);
+
--- a/include/u.h
+++ b/include/u.h
@@ -12,8 +12,15 @@
 typedef unsigned long uint32;
 typedef long int32;
 
+typedef char* va_list;
 typedef struct
 {
 	void *val;
 	void *next;
 }ll_t;
+
+typedef struct
+{
+	char *name;
+	int (*main)(int argc, char **argv);
+}prog_t;
--- a/libc/lladd.c
+++ b/libc/lladd.c
@@ -5,7 +5,7 @@
 int
 lladd(ll_t *last, void *data)
 {
-	ll_t *temp = malloc(sizeof(ll_t*));
+	ll_t *temp;
 
 	temp->val = data;
 	temp->next = nil;
@@ -13,6 +13,8 @@
 	if(last->next != nil)
 		return LL_ERR;
 
+	temp = malloc(sizeof(ll_t*));
+	
 	last->next = temp;
 	return OK;
 }
--- a/libc/lldel.c
+++ b/libc/lldel.c
@@ -1,12 +1,16 @@
+#include <u.h>
+#include <err.h>
+#include <mem.h>
+
 /* deletes the next entry in the list */
 int
 lldel(ll_t *ll)
 {
 	ll_t *temp = ll->next;
-	if(ll->next != nil)
-		return LL_ERR;
 
-	ll->next = ll->next->next;
+	ll->next = temp->next;
+	
+	free(temp->val);
 	free(temp);
 	return OK;
 }
--- /dev/null
+++ b/libc/strccnt.c
@@ -1,0 +1,18 @@
+#include <u.h>
+#include <libc.h>
+
+int
+strccnt(char *s, char c)
+{
+	int i, t;
+	
+	i = 0;
+	t = 0;
+	while(i < strlen(s))
+	{
+		if(s[i] == c)
+			t++;
+		i++;
+	}
+	return t;
+}
--- /dev/null
+++ b/libc/strcntok.c
@@ -1,0 +1,42 @@
+#include <u.h>
+#include <libc.h>
+
+#include <mem.h>
+	
+char*
+strcntok(char *src, char token, int n)
+{
+	int i, b, match, lastmatch, lastnotmatch;
+	char *res;
+			
+	match = -1; /* n = 0, match++ = 0 */
+	lastmatch = 0;
+	i = 0;
+	while(i < strlen(src))
+	{
+		if(src[i] == token)
+		{
+			match++;
+			if(match == n)
+			{
+				res = malloc(i + 1 - lastmatch); /* i - lastmatch + '\0' */
+				/* TODO: use strncpy */	
+				memcpy(res, src + lastmatch, i - lastmatch);
+				res[i - lastmatch] = '\0';
+				return res;
+			}
+
+			lastmatch = i+1;
+		}
+		i++;
+	}
+	
+	/* last instance would return anything left */
+	if(n == match + 1)
+	{
+		res = malloc(i - lastmatch);
+		memcpy(res, src + lastmatch, i - lastmatch);
+		return res;	
+	}
+	return nil;
+}
--- a/libc/strlen.c
+++ b/libc/strlen.c
@@ -1,8 +1,8 @@
-int
+unsigned int
 strlen(char *s)
 {
 	int i = 0;
-	while(s[i])
+	while(s[i] != '\0')
 		i++;
 	return i;
-}
\ No newline at end of file
+}
--- a/pc/boot.s
+++ b/pc/boot.s
@@ -33,7 +33,7 @@
 .section .bss
 .align 16
 stack_bottom:
-.skip 16384 # 16 KiB
+.skip 32768 # 32 KiB
 stack_top:
 
 .section .text
--- a/pc/com.c
+++ b/pc/com.c
@@ -77,17 +77,4 @@
 com_getc(void)
 {
 	return com_getchar(COM1);
-}
-
-char*
-com_getl(void)
-{
-	char *cmd, c;
-	int i = 0;
-	/* might c be '\n'? unlikely */
-	while(c != '\n')
-	{
-		cmd[i] = c;
-	}
-	return cmd;
 }
\ No newline at end of file
--- a/pc/kern.c
+++ b/pc/kern.c
@@ -3,88 +3,27 @@
 #include <mem.h>
 #include <cons.h>
 #include <pccons.h>
-#include <bitcons.h>
+#include "../cmd/rc.h"
 
+#include <vga.h>
+#include <ps2.h>
+
+
 /* abandon hope, all ye who enter here */
 void
 panic(void)
 {
-	conswrite(pccons, "panic: give up. it's over.\n");
+	vga_puts("panic: give up. it's over.\n");
 }
 
-int
-run(char* cmd)
-{
-	/* replace it with a proper table */
-	if(!strcmp(cmd, "clear"))
-	{
-		consclear(pccons, ' ');
-	}
-	else if(!strcmp(cmd, "hello"))
-	{
-		conswrite(pccons, "hi");
-	}
-	else if(!strcmp(cmd, "reboot"))
-		return 0;
-	else
-	{
-		conswrite(pccons, "no such command");
-	}
-
-	conswrite(pccons, "\n");
-	conswrite(pccons, "> ");
-	return 1;
-
-}
-
 void
-repl(void)
-{
-	char c;
-	char *cmd;
-
-	int i = 0;
-	memset(cmd, 0, 16); 
-	conswrite(pccons, "> ");
-	while(1)
-	{
-
-		c = consread(pccons);
-
-		consputc(pccons, c);
-
-		if(c == '\r' || c == '\n')
-		{
-			if(!run(cmd))
-				return;
-
-			/* clear the mess */
-			cmd = malloc(16);
-			i = 0;	
-		}
-		else if(c != '\b')
-		{
-			*(cmd+i) = c;
-			i++;
-		}
-		else
-		{
-			/* we don't want a negative i */
-			if(i)
-				i--;
-			*(cmd+i) = 0;
-			
-		}
-	}
-}
-
-void
 kernel_main(void) 
 {
+	/* set up memory map */
 	memset(memap, FREE, MEM_MAX * (1024 / BLOCKSIZE));
 
-	consinit(pccons);
-	conswrite(bitcons, "Teppich");
+	vga_init();
+	vga_puts("Teppich\n");
 	
-	repl();
+	rc_main();
 }
--- a/pc/mem.c
+++ b/pc/mem.c
@@ -5,7 +5,6 @@
 
 /* does first fit, returns index of that part of memory in memap */
 int
-
 _malloc(uint16 size)
 {
 	int i, j;
@@ -25,7 +24,7 @@
 			{
 	
 				/* we are done here, give address */
-				for(int j = i ; j > i - size; j--)
+				for(j = i ; j > i - size; j--)
 					memap[j] = TAKEN;
 			 	return i - size;
 			}
--- a/pc/vga.c
+++ b/pc/vga.c
@@ -128,7 +128,9 @@
 void
 vga_puts(char *s)
 {
-	int len = strlen(s);
+	int len;
+	
+	len = strlen(s);
 	for(int i = 0 ; i < len ; i++)
 		vga_putc(s[i]);
 }