]> pd.if.org Git - zos/commitdiff
klib and makefile
authorNathan Wagner <nw@hydaspes.if.org>
Tue, 25 Oct 2016 01:27:31 +0000 (20:27 -0500)
committerNathan Wagner <nw@hydaspes.if.org>
Tue, 25 Oct 2016 01:27:31 +0000 (20:27 -0500)
18 files changed:
Makefile [new file with mode: 0644]
klib/bitops.s [new file with mode: 0644]
klib/memcpy.c [new file with mode: 0644]
klib/memmove.c [new file with mode: 0644]
klib/memset.c [new file with mode: 0644]
klib/objlist.c [new file with mode: 0644]
klib/objlist.h [new file with mode: 0644]
klib/printk.c [new file with mode: 0644]
klib/printk.h [new file with mode: 0644]
klib/strcat.c [new file with mode: 0644]
klib/strcmp.c [new file with mode: 0644]
klib/strcpy.c [new file with mode: 0644]
klib/strcspn.c [new file with mode: 0644]
klib/strdup.c [new file with mode: 0644]
klib/string.h [new file with mode: 0644]
klib/strlen.c [new file with mode: 0644]
klib/strncpy.c [new file with mode: 0644]
klib/strtok.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..e4cab80
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,129 @@
+AFLAGS=-felf64
+AS=yasm $(AFLAGS)
+CFLAGS= -ffreestanding -mno-red-zone  -mcmodel=large
+CFLAGS= -Wall -Iinclude -Ipci -Iklib -I. -std=c99 -nostdlibinc -Wno-parentheses -ffreestanding -mcmodel=large -mno-red-zone -mno-mmx -mno-sse -mno-sse2 -fomit-frame-pointer
+LDFLAGS= -L. -Tlink64.ld
+CFLAGS32= -ffreestanding -mno-red-zone -mno-mmx -mno-sse -mno-sse2
+OS=$(shell uname -s)
+
+DIS= objdump -M intel -d
+
+LIBSRC=$(wildcard klib/*.c)
+#LIBOBJS:=$(addsuffix .o,$(basename, $(wildcard klib/*.c)))
+LIBOBJS:=$(addsuffix .o, $(basename $(wildcard klib/*.c)))
+#LIBOBJS:=$(addprefix klib/, $(LIBOBJS))
+
+#PATH:=/home/nw/src/kernel/cc/sysroot/bin:$(PATH)
+#export PATH
+
+CC=clang -target amd64-elf-zos
+LD=ld
+OBJCOPY=objcopy
+
+ifeq ($(OS),Darwin)
+#      CC=/opt/local/libexec/llvm-3.9/bin/clang
+       LD=x86_64-elf-ld
+       AR=x86_64-elf-ar
+       OBJCOPY=x86_64-elf-objcopy
+endif
+
+zos: zos64
+       $(OBJCOPY) $< -O elf32-i386 $@
+
+usermode.o: usermode.c
+       $(CC) $(CFLAGS) -fpic -c -o $@ $<
+
+include/errno.h: include/errno.in tools/mkerrno
+       tools/mkerrno $< > $@
+
+libklib.a: CFLAGS+=-D_PDCLIB_restrict=restrict
+libklib.a: $(LIBOBJS)
+       $(AR) rcu $@ $(LIBOBJS)
+
+vfs/vfs.o: vfs/vfs.c vfs/vfs.h | include/errno.h
+vfs/pipes.o: vfs/pipes.c vfs/vfs.h | include/errno.h
+
+libvfs.a: vfs/pipes.o vfs/vfs.o
+       $(AR) rcu $@ $+
+
+pci/func.o: pci/func.c
+
+libpci.a: pci/pci.o pci/func.o
+       $(AR) rcu $@ $+
+
+pic.o: pic.h interrupt.h
+
+zos64: libklib.a
+zos64: link64.ld
+
+KOBJS= boot32.o bootz.o kernel.o interrupt.o idt.o \
+       pic.o ioport.o timer.o tty.o mem.o \
+       memx64.o spinlock.o process.o taskx64.o kbd.o \
+       cpu.o syscalls.o smp.o \
+       usermain.o
+KLIBS=libpci.a libklib.a
+
+zos64: $(KOBJS) $(KLIBS) link64.ld
+       $(LD) $(LDFLAGS) -z max-page-size=0x1000 -nostdlib $(KOBJS) $(KLIBS) -o $@
+
+zemu: zos
+       #qemu-system-x86_64 -d in_asm,op -m 512M -kernel $< -vnc :0
+       qemu-system-x86_64 -monitor stdio -m 256MB -kernel $< -vnc :0 -append 'mboot hb' \
+                   -drive file=rdisk.img,if=none,id=mydisk \
+                       -device ich9-ahci,id=ahci \
+                           -device ide-drive,drive=mydisk,bus=ahci.0
+                   #-device ide-hd,drive=mydisk
+cemu: zos
+       #qemu-system-x86_64 -d in_asm,op -m 512M -kernel $< -vnc :0
+       qemu-system-x86_64 -monitor stdio -m 256MB -kernel $< -display curses -append 'mboot hb' \
+                   -drive file=rdisk.img,if=none,id=mydisk \
+                       -device ich9-ahci,id=ahci \
+                           -device ide-drive,drive=mydisk,bus=ahci.0
+                   #-device ide-hd,drive=mydisk
+
+rdisk.img:
+       qemu-img create -f qcow2 $@ 1G
+
+mem.o: mem.c mem.h multiboot.h
+interrupt.o: interrupt.c interrupt.h
+process.o: process.c process.h
+
+#              -initrd TODO
+memu: zos rdisk.img
+       #qemu-system-x86_64 -d in_asm,op -m 512M -kernel $< -vnc :0
+       qemu-system-x86_64 $(SMP) -d cpu_reset -monitor stdio -m 256MB \
+               -kernel $< -append 'mboot hb' \
+                   -drive file=rdisk.img,if=none,id=mydisk \
+                       -device ich9-ahci,id=ahci \
+                           -device ide-drive,drive=mydisk,bus=ahci.0
+                   #-device ide-hd,drive=mydisk
+
+cemu2: zos
+       qemu-system-x86_64 -display curses -m 512M -kernel $< -append 'mboot hb'
+
+kernel.o: kernel.c multiboot.h
+       $(CC) $(CFLAGS) -o $@ -c $<
+
+clean:
+       rm -f *.o *.a zos64 zos klib/*.o vfs/*.o pci/*.o ahci/*.o
+
+%.o%.s:
+       $(AS) -o $@ $<
+
+%.o%.c:
+       $(CC) $(CFLAGS) -c -o $@ $<
+
+tprintk.o: printk.c
+       cc -Wall -Wno-parentheses -I. -c -o $@ $+
+
+test: t/t_printk tprintk.o
+       t/t_printk
+
+t/t_printk.o: t/t_printk.c
+       cc -Wall -I. -c -o $@ $+
+
+t/t_printk: tprintk.o t/t_printk.o
+       cc -Wall -o $@ $+
+
+%.d%.o:
+       $(DIS) $<
diff --git a/klib/bitops.s b/klib/bitops.s
new file mode 100644 (file)
index 0000000..2771bcb
--- /dev/null
@@ -0,0 +1,10 @@
+; round up to a power of two
+logtwoup:
+       xor eax, eax
+       bsr rsi, rdi ; rsi has the log 2 rounded down
+       bts rax, rsi
+       cmp rax, rdi
+       jz .done
+       shr rax, 1
+.done:
+       ret
diff --git a/klib/memcpy.c b/klib/memcpy.c
new file mode 100644 (file)
index 0000000..fc5e053
--- /dev/null
@@ -0,0 +1,10 @@
+#include <string.h>
+
+void *memcpy(void *restrict s1, const void *restrict s2, size_t n) {
+       char *dest = (char *)s1;
+       const char *src = (const char *)s2;
+       while (n--) {
+               *dest++ = *src++;
+       }
+       return s1;
+}
diff --git a/klib/memmove.c b/klib/memmove.c
new file mode 100644 (file)
index 0000000..b372945
--- /dev/null
@@ -0,0 +1,18 @@
+#include <string.h>
+
+void *memmove(void *s1, const void *s2, size_t n) {
+       char *dest = (char *)s1;
+       const char *src = (const char *)s2;
+       if (dest <= src) {
+               while (n--) {
+                       *dest++ = *src++;
+               }
+       } else {
+               src += n;
+               dest += n;
+               while (n--) {
+                       *--dest = *--src;
+               }
+       }
+       return s1;
+}
diff --git a/klib/memset.c b/klib/memset.c
new file mode 100644 (file)
index 0000000..afa52a7
--- /dev/null
@@ -0,0 +1,11 @@
+#include <string.h>
+
+void *memset(void *s, int c, size_t n) {
+       unsigned char *p = (unsigned char *)s;
+
+       while (n--) {
+               *p++ = (unsigned char)c;
+       }
+
+       return s;
+}
diff --git a/klib/objlist.c b/klib/objlist.c
new file mode 100644 (file)
index 0000000..ce3bd0d
--- /dev/null
@@ -0,0 +1,52 @@
+#include "objlist.h"
+
+#include "mem.h"
+
+/*
+ * how to have an empty list
+ */
+struct kobj_list *list_init() {
+       struct kobj_list *list;
+       list = koalloc(sizeof *list);
+       list->next = 0;
+       list->prev = 0;
+       list->flags = 0;
+       return list;
+}
+
+/* add an object pointer to the end of the list */
+void list_push(struct kobj_list *list, void *obj) {
+       
+}
+
+void *list_pop(struct kobj_list *list, void *obj) {
+       return 0;
+}
+
+void *list_shift(struct kobj_list *list, void *obj) {
+       return 0;
+}
+
+void list_unshift(struct kobj_list *list, void *obj) {
+}
+
+void list_free(struct kobj_list *list, void *obj) {
+}
+
+#if 0
+for (cur = list; cur != list; cur = cur->next) {
+       
+}
+#endif
+void *list_elem(struct kobj_list *list, uint64_t elem) {
+       return 0;
+#if 0
+       if (elem > list->elements) return 0;
+
+       while (elem > KOLIST_MAX_INDEX) {
+               list = list->next;
+               elem -= KOLIST_MAX_INDEX+1;
+       }
+       return list->obj[elem];
+#endif
+}
diff --git a/klib/objlist.h b/klib/objlist.h
new file mode 100644 (file)
index 0000000..dacfad4
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef KERNEL_DS_H_
+#define KERNEL_DS_H_ 1
+
+#include <stdint.h>
+
+#define KOLIST_MAX_INDEX 507
+/* an empty list has next and prev pointers null */
+/* or, use one as a sentinel? could store an object count in the flags then */
+struct kobj_list {
+        struct kobj_list *next;
+        struct kobj_list *prev;
+       void *obj; /* a pointer to where a new object would go */
+        /* we've got room for 32 bytes, might as well have some flags */
+        uint64_t flags; 
+};
+
+#endif
diff --git a/klib/printk.c b/klib/printk.c
new file mode 100644 (file)
index 0000000..5df47ab
--- /dev/null
@@ -0,0 +1,359 @@
+/* adapted from http://www.efgh.com/software/gprintf.htm */
+/* public domain */
+
+#include <stdarg.h>
+#include <stdint.h>
+#include <stddef.h>
+
+#include "kernel.h"
+#include "tty.h"
+
+#define BITS_PER_BYTE 8
+
+#define F_THOUSANDS   0x1
+#define F_LEFTJUSTIFY 0x2
+#define F_USESIGN     0x4
+#define F_SPACE       0x8
+#define F_ALTERNATE   0x10
+#define F_ZEROPAD     0x20
+#define F_CAPITAL     0x40
+/* F_PRECISION set if precision specified in format */
+#define F_PRECISION   0x80
+
+#if 0
+static unsigned char digits[17]    = "01234567890abcdef";
+static unsigned char capdigits[17] = "01234567890ABCDEF";
+#endif
+
+struct parameters {
+       int n; /* number of output chars */
+       unsigned flags;
+       int width;
+       int precision;
+       int modifier;
+
+       short len;
+       int (*output_function)(void *, int);
+       void *output_pointer;
+       char *str;
+       char buf[BITS_PER_BYTE * sizeof(uintmax_t) + 1];
+};
+
+static int strlenk(char *s) {
+       int len = 0;
+       while (*s++) {
+               len++;
+       }
+       return len;
+}
+
+static void output(struct parameters *p, char *s) {
+       int justify = p->width - p->len;
+       char jc = ' ';
+
+       if (justify < 0) {
+               justify = 0;
+       }
+
+       if (justify && p->flags & F_ZEROPAD) {
+               jc = '0';
+       }
+
+       if (justify && !(p->flags & F_LEFTJUSTIFY)) {
+               while (justify--) {
+                       terminal.putchar(jc);
+                       p->n++;
+               }
+       }
+
+       while (p->len--) {
+               terminal.putchar(*s++);
+               p->n++;
+       }
+
+       while (justify-- > 0) {
+               terminal.putchar(' ');
+               p->n++;
+       }
+}
+
+static inline int get_decimal(const char *str, int *val) {
+       int ans = 0;
+       int used = 0;
+       int neg = 0;
+       char digit;
+
+       if (*str == '-') {
+               str++;
+               neg = 1;
+               used++;
+       }
+
+       while (digit = *str++) {
+               if (digit >= '0' && digit <= '9') {
+                       ans *= 10;
+                       ans += (digit - '0');
+                       used++;
+               } else {
+                       break;
+               }
+       }
+       if (neg) {
+               ans = -ans;
+       }
+       *val = ans;
+       return used;
+}
+
+int printk(const char *fmt, ...) {
+       va_list ap;
+       int n;
+       va_start(ap, fmt);
+       n = printkv(fmt, ap);
+       va_end(ap);
+       return n;
+}
+
+int printkv(const char *fmt, va_list ap) {
+       struct parameters p = { 0 };
+       struct parameters z = { 0 };
+       unsigned char fc;
+       int get_flags;
+
+       while (fc = *fmt++) {
+               if (fc != '%') {
+                       terminal.putchar(fc);
+                       p.n++;
+                       continue;
+               }
+               p = z;
+
+               /* it's a conversion, get flags */
+               get_flags = 1;
+               while (get_flags) {
+                       fc = *fmt++;
+                       switch (fc) {
+                               case 0:
+                                       /* we're done */
+                                       /* this is an error though */
+                                       return p.n;
+                                       break;
+                               case '#':
+                                       p.flags |= F_ALTERNATE;
+                                       break;
+                               case '0':
+                                       p.flags |= F_ZEROPAD;
+                                       break;
+                               case '-':
+                                       p.flags |= F_LEFTJUSTIFY;
+                                       break;
+                               case ' ':
+                                       p.flags |= F_SPACE;
+                                       break;
+                               case '+':
+                                       p.flags |= F_USESIGN;
+                                       break;
+                               /* posix, not C, so maybe need a define */
+                               case '.':
+                                       p.flags |= F_THOUSANDS;
+                                       break;
+                               default:
+                                       fmt--;
+                                       get_flags = 0;
+                                       break;
+                       }
+               }
+
+               /* get minimum field width */
+               if (fc >= '1' && fc <= '9') {
+                       fmt += get_decimal(fmt, &p.width);
+               } else if (*fmt == '*') {
+                       fmt++;
+                       if (*fmt >= '1' && *fmt <= '9') {
+                               int lenarg = 0;
+                               fmt += get_decimal(fmt, &lenarg);
+                               if (*fmt != '$') {
+                                       /* TODO ERROR */
+                               }
+                               fmt++; /* skip past the $ */
+                       } else {
+                               p.width = va_arg(ap, int);
+                               if (p.width < 0) {
+                                       p.width = -p.width;
+                                       p.flags |= F_LEFTJUSTIFY;
+                               }
+                       }
+               }
+
+               /* get precision */
+               if (*fmt == '.') {
+                       fmt++;
+                       p.precision = 0;
+                       p.flags |= F_PRECISION;
+
+                       if (fc >= '0' && fc <= '9') {
+                               fmt += get_decimal(fmt, &p.width);
+                       } else if (*fmt == '*') {
+                               fmt++;
+                               if (*fmt >= '1' && *fmt <= '9') {
+                                       int arg = 0;
+                                       fmt += get_decimal(fmt, &arg);
+                                       if (*fmt != '$') {
+                                               /* TODO ERROR */
+                                       }
+                                       fmt++; /* skip past the $ */
+                               } else {
+                                       p.precision = va_arg(ap, int);
+                                       if (p.precision < 0) {
+                                               p.precision = 0;
+                                               p.flags &= ~F_PRECISION;
+                                       }
+                               }
+                       }
+               }
+
+               /* get length modifier */
+               switch (*fmt) {
+                       case 'L':
+                       case 'j':
+                       case 'z':
+                       case 't':
+                               p.modifier = *fmt++;
+                               break;
+                       case 'h':
+                               p.modifier = *fmt++;
+                               if (*fmt == 'h') {
+                                       fmt++;
+                                       p.modifier = 'H';
+                               }
+                               break;
+                       case 'l':
+                               p.modifier = *fmt++;
+                               if (*fmt == 'l') {
+                                       fmt++;
+                                       p.modifier = 'L';
+                               }
+                               break;
+                       default:
+                               break;
+               }
+
+               /* conversion specifier */
+               int base = 2;
+               uintmax_t i;
+               union {
+                       uintmax_t uim;
+                       int i;
+                       char c;
+                       unsigned u;
+                       unsigned char uc;
+                       unsigned short us;
+                       unsigned long ul;
+                       unsigned long long ull;
+                       size_t size;
+                       ptrdiff_t pd;
+               } arg;
+
+               switch (*fmt) {
+                       case '%':
+                               terminal.putchar('%');
+                               p.n++;
+                               fmt++;
+                               break;
+                       case 'c':
+                               if (p.modifier == 'l') {
+                                       /* wide int wint_t */
+                                       break;
+                               }
+                               arg.i = va_arg(ap, int);
+                               p.buf[0] = (unsigned char) arg.i;
+                               p.len = 1;
+                               output(&p, p.buf);
+                               fmt++;
+                               break;
+                       case 's':
+                               p.str = va_arg(ap, char *);
+                               /* TODO may not be properly terminated if precision is given */
+                               p.len = strlenk(p.str);
+                               /* precision, if given, is maximum characters
+                                * for an 's' conversion */
+                               if (p.flags & F_PRECISION && p.len > p.precision) {
+                                       p.len = p.precision;
+                               }
+                               /* TODO don't zero pad strings */
+                               output(&p, p.str);
+                               fmt++;
+                               break;
+                       case 'X':
+                               p.flags |= F_CAPITAL;
+                       case 'x':
+                               base += 6;
+                       case 'u':
+                               base += 2;
+                       case 'o':
+                               base += 6;
+                               switch (p.modifier) {
+                                       case 'H':
+                                               arg.u = va_arg(ap, unsigned int);
+                                               i = (uintmax_t) (unsigned char) arg.uc;
+                                               break;
+                                       case 'h':
+                                               arg.u = va_arg(ap, unsigned int);
+                                               i = (uintmax_t) (unsigned short) arg.us;
+                                               break;
+                                       case 'l':
+                                               arg.ul = va_arg(ap, unsigned long);
+                                               i = (uintmax_t) arg.ul;
+                                               break;
+                                       case 'L':
+                                               arg.ull = va_arg(ap, unsigned long long);
+                                               i = (uintmax_t) arg.ull;
+                                               break;
+                                       case 'j':
+                                               i =  va_arg(ap, uintmax_t);
+                                               break;
+                                       case 'z':
+                                               arg.size = va_arg(ap, size_t);
+                                               i = (uintmax_t) arg.size;
+                                               break;
+                                       case 't':
+                                               arg.pd = va_arg(ap, ptrdiff_t);
+                                               i = (uintmax_t) arg.pd;
+                                               break;
+                                       default:
+                                               arg.u = va_arg(ap, unsigned);
+                                               i = (uintmax_t) arg.u;
+                                               break;
+                               }
+                               p.str = p.buf + sizeof(p.buf) - 1;
+                               *p.str = 0;
+                               p.str--;
+                               do {
+                                       int c;
+                                       c = i % base + '0';
+                                       if (c > '9') {
+                                               if (p.flags & F_CAPITAL)
+                                                       c += 'A'-'9'-1;
+                                               else
+                                                       c += 'a'-'9'-1;
+                                       }
+                                       *p.str-- = c;
+                                       p.len++;
+                               } while ( i /= base);
+                               output(&p, p.str+1);
+                               fmt++;
+                               break;
+                       case 'd':
+                       case 'i':
+                               base = 10;
+
+                       default:
+                               break;
+               }
+               /* output number here ? */
+
+       }
+       terminal.update_cursor();
+
+       return p.n;
+}
diff --git a/klib/printk.h b/klib/printk.h
new file mode 100644 (file)
index 0000000..436dbf9
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef PRINTK_H_
+#define PRINTK_H_
+
+#include <stdint.h>
+
+void terminal_putchar(int ch);
+int printk(const char *fmt, ...);
+
+#endif
diff --git a/klib/strcat.c b/klib/strcat.c
new file mode 100644 (file)
index 0000000..33e2648
--- /dev/null
@@ -0,0 +1,10 @@
+#include <string.h>
+
+char *strcat(char *s1, const char *s2) {
+       char *rc = s1;
+       if (*s1) {
+               while(*++s1);
+       }
+       while ( (*s1++ = *s2++) );
+       return rc;
+}
diff --git a/klib/strcmp.c b/klib/strcmp.c
new file mode 100644 (file)
index 0000000..6d46c95
--- /dev/null
@@ -0,0 +1,9 @@
+#include <string.h>
+
+int strcmp(const char *s1, const char *s2) {
+       while ( *s1 && (*s1 == *s2) ) {
+               ++s1;
+               ++s2;
+       }
+       return *(unsigned char *)s1 - *(unsigned char *)s2;
+}
diff --git a/klib/strcpy.c b/klib/strcpy.c
new file mode 100644 (file)
index 0000000..75d9d85
--- /dev/null
@@ -0,0 +1,7 @@
+#include <string.h>
+
+char *strcpy(char *s1, const char *s2) {
+       char *rc = s1;
+       while ( ( *s1++ = *s2++ ) );
+       return rc;
+}
diff --git a/klib/strcspn.c b/klib/strcspn.c
new file mode 100644 (file)
index 0000000..8970175
--- /dev/null
@@ -0,0 +1,17 @@
+#include <string.h>
+
+size_t strcspn(const char *s1, const char *s2) {
+       size_t len = 0;
+       const char *p;
+
+       while (s1[len]) {
+               p = s2;
+               while (*p) {
+                       if (s1[len] == *p++) {
+                               return len;
+                       }
+               }
+               ++len;
+       }
+       return len;
+}
diff --git a/klib/strdup.c b/klib/strdup.c
new file mode 100644 (file)
index 0000000..b921b85
--- /dev/null
@@ -0,0 +1,15 @@
+#include <string.h>\r
+#include <stdlib.h>\r
+\r
+char *strdup(const char *s) {\r
+       char *ns = NULL;\r
+       size_t len;\r
+\r
+       if (s) {\r
+               len = strlen(s) + 1;\r
+               ns = malloc(len);\r
+               if (ns)\r
+                       strncpy(ns, s, len);\r
+       }\r
+       return ns;\r
+}\r
diff --git a/klib/string.h b/klib/string.h
new file mode 100644 (file)
index 0000000..3b01407
--- /dev/null
@@ -0,0 +1,43 @@
+#ifndef _STRING_H
+#define _STRING_H
+
+#include <stddef.h>
+
+void *memccpy(void *, const void *, int, size_t);
+void *memchr(const void *, int, size_t);
+void *memrchr(const void *, int, size_t);
+int memcmp(const void *, const void *, size_t);
+void *memcpy(void *, const void *, size_t);
+void *memmove(void *, const void *, size_t);
+void *memset(void *, int, size_t);
+void *memmem(const void *, size_t, const void *, size_t);
+void memswap(void *, void *, size_t);
+void bzero(void *, size_t);
+int strcasecmp(const char *, const char *);
+int strncasecmp(const char *, const char *, size_t);
+char *strcat(char *, const char *);
+char *strchr(const char *, int);
+char *index(const char *, int);
+char *strrchr(const char *, int);
+char *rindex(const char *, int);
+int strcmp(const char *, const char *);
+char *strcpy(char *, const char *);
+size_t strcspn(const char *, const char *);
+char *strdup(const char *);
+char *strndup(const char *, size_t);
+char *strerror(int);
+char *strsignal(int);
+size_t strlen(const char *);
+size_t strnlen(const char *, size_t);
+char *strncat(char *, const char *, size_t);
+size_t strlcat(char *, const char *, size_t);
+int strncmp(const char *, const char *, size_t);
+char *strncpy(char *, const char *, size_t);
+size_t strlcpy(char *, const char *, size_t);
+char *strpbrk(const char *, const char *);
+size_t strspn(const char *, const char *);
+char *strstr(const char *, const char *);
+char *strtok(char *, const char *);
+char *strtok_r(char *, const char *, char **);
+
+#endif
diff --git a/klib/strlen.c b/klib/strlen.c
new file mode 100644 (file)
index 0000000..861f843
--- /dev/null
@@ -0,0 +1,11 @@
+#include <string.h>
+
+size_t strlen(const char *s) {
+       size_t rc = 0;
+
+       while (s[rc]) {
+               ++rc;
+       }
+
+       return rc;
+}
diff --git a/klib/strncpy.c b/klib/strncpy.c
new file mode 100644 (file)
index 0000000..e674420
--- /dev/null
@@ -0,0 +1,17 @@
+#include <string.h>
+
+char *strncpy(char *s1, const char *s2, size_t n) {
+       char * rc = s1;
+       while ( (n > 0) && (*s1++ = *s2++) ) {
+               /* Cannot do "n--" in the conditional as size_t is unsigned and we have
+                * to check it again for >0 in the next loop below, so we must not risk
+                * underflow.
+                */
+               --n;
+       }
+       /* Checking against 1 as we missed the last --n in the loop above. */
+       while (n-- > 1) {
+               *s1++ = '\0';
+       }
+       return rc;
+}
diff --git a/klib/strtok.c b/klib/strtok.c
new file mode 100644 (file)
index 0000000..d3595a3
--- /dev/null
@@ -0,0 +1,52 @@
+#include <string.h>
+
+char *strtok(char *s1, const char *s2) {
+       static char *tmp = NULL;
+       const char *p = s2;
+
+       if (s1 != NULL) {
+               /* new string */
+               tmp = s1;
+       } else {
+               /* old string continued */
+               if (tmp == NULL) {
+                       /* No old string, no new string, nothing to do */
+                       return NULL;
+               }
+               s1 = tmp;
+       }
+
+       /* skipping leading s2 characters */
+       while (*p && *s1) {
+               if ( *s1 == *p ) {
+                       /* found seperator; skip and start over */
+                       ++s1;
+                       p = s2;
+                       continue;
+               }
+               ++p;
+       }
+
+       if (!*s1) {
+               /* no more to parse */
+               return ( tmp = NULL );
+       }
+
+       /* skipping non-s2 characters */
+       tmp = s1;
+       while (*tmp) {
+               p = s2;
+               while (*p) {
+                       if (*tmp == *p++) {
+                               /* found seperator; overwrite with '\0', position tmp, return */
+                               *tmp++ = '\0';
+                               return s1;
+                       }
+               }
+               ++tmp;
+       }
+
+       /* parsed to end of string */
+       tmp = NULL;
+       return s1;
+}