diff options
Diffstat (limited to 'kernel/lib')
-rw-r--r-- | kernel/lib/atox.c | 29 | ||||
-rw-r--r-- | kernel/lib/bound.c | 12 | ||||
-rw-r--r-- | kernel/lib/btoa.c | 43 | ||||
-rw-r--r-- | kernel/lib/ctoi.c | 14 | ||||
-rw-r--r-- | kernel/lib/fputc.c | 10 | ||||
-rw-r--r-- | kernel/lib/isdigit.c | 6 | ||||
-rw-r--r-- | kernel/lib/isspace.c | 16 | ||||
-rw-r--r-- | kernel/lib/itoc.c | 10 | ||||
-rw-r--r-- | kernel/lib/kalloc.c | 210 | ||||
-rw-r--r-- | kernel/lib/kprintf.c | 576 | ||||
-rw-r--r-- | kernel/lib/memcmp.c | 9 | ||||
-rw-r--r-- | kernel/lib/memcpy.c | 10 | ||||
-rw-r--r-- | kernel/lib/memcpyv.c | 11 | ||||
-rw-r--r-- | kernel/lib/memmove.c | 20 | ||||
-rw-r--r-- | kernel/lib/memmovev.c | 20 | ||||
-rw-r--r-- | kernel/lib/memset.c | 10 | ||||
-rw-r--r-- | kernel/lib/memsetv.c | 10 | ||||
-rw-r--r-- | kernel/lib/panic.c | 6 | ||||
-rw-r--r-- | kernel/lib/stpcpy.c | 9 | ||||
-rw-r--r-- | kernel/lib/stpncpy.c | 10 | ||||
-rw-r--r-- | kernel/lib/strcat.c | 7 | ||||
-rw-r--r-- | kernel/lib/strcpy.c | 9 | ||||
-rw-r--r-- | kernel/lib/strlen.c | 9 | ||||
-rw-r--r-- | kernel/lib/strncmp.c | 11 | ||||
-rw-r--r-- | kernel/lib/strncpy.c | 10 | ||||
-rw-r--r-- | kernel/lib/strtoux.c | 43 | ||||
-rw-r--r-- | kernel/lib/strtox.c | 52 | ||||
-rw-r--r-- | kernel/lib/uxtoa.c | 27 | ||||
-rw-r--r-- | kernel/lib/xtoa.c | 31 |
29 files changed, 1227 insertions, 13 deletions
diff --git a/kernel/lib/atox.c b/kernel/lib/atox.c new file mode 100644 index 0000000..6d3d4cc --- /dev/null +++ b/kernel/lib/atox.c @@ -0,0 +1,29 @@ +#include <lib.h> + +#define ATOX(name, type) \ + type name(const char *s) \ + { \ + for (; isspace(*s); s++) \ + ; \ + int neg = 0; \ + switch (*s) { \ + case '-': \ + neg = 1; \ + /* fallthrough */ \ + case '+': \ + s++; \ + break; \ + } \ + type num = 0; \ + for (; *s == '0'; s++) \ + ; \ + for (; isdigit(*s); s++) { \ + num *= 10; \ + num += *s - '0'; \ + } \ + return num * (neg ? -1 : 1); \ + } + +ATOX(atoi, int) +ATOX(atol, long int) +ATOX(atoll, long long int) diff --git a/kernel/lib/bound.c b/kernel/lib/bound.c new file mode 100644 index 0000000..5a3c9fa --- /dev/null +++ b/kernel/lib/bound.c @@ -0,0 +1,12 @@ +#include <lib.h> + +unsigned int bound(unsigned int min, unsigned int value, unsigned int max) +{ + if (value < min) { + value = min; + } + if (value > max) { + value = max; + } + return value; +} diff --git a/kernel/lib/btoa.c b/kernel/lib/btoa.c new file mode 100644 index 0000000..96a60ef --- /dev/null +++ b/kernel/lib/btoa.c @@ -0,0 +1,43 @@ +#include <lib.h> + +static char suffixes[] = { 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'R', 'Q' }; + +char *btoa(size_t bytes, char *buf) +{ + // no suffix if under 1K, print up to four digits + if (bytes < 1024) { + ultoa(bytes, buf, 10); + return buf; + } + + // store one digit of remainder for decimal + unsigned int remainder; + // power of 1024 + int power = 0; + + // iterate until remaining bytes fits in three digits + while (bytes >= 1000) { + remainder = (bytes % 1024) * 10 / 1024; + bytes /= 1024; + power += 1; + } + + // end of number + char *end; + + if (bytes >= 10) { + // no decimal + end = ultoa(bytes, buf, 10); + } else { + // decimal + end = ultoa(bytes, buf, 10); + end[0] = '.'; + end = ultoa(remainder, end + 1, 10); + } + + // add suffix + end[0] = suffixes[power - 1]; + end[1] = '\0'; + + return buf; +} diff --git a/kernel/lib/ctoi.c b/kernel/lib/ctoi.c new file mode 100644 index 0000000..09a9f10 --- /dev/null +++ b/kernel/lib/ctoi.c @@ -0,0 +1,14 @@ +#include <lib.h> + +int ctoi(char c) +{ + if (c >= '0' && c <= '9') { + return c - '0'; + } else if (c >= 'A' && c <= 'Z') { + return c - 'A' + 10; + } else if (c >= 'a' && c <= 'z') { + return c - 'a' + 10; + } else { + return -1; + } +} diff --git a/kernel/lib/fputc.c b/kernel/lib/fputc.c deleted file mode 100644 index 0d47cb5..0000000 --- a/kernel/lib/fputc.c +++ /dev/null @@ -1,10 +0,0 @@ -#include <lib.h> -#include <comus/drivers/tty.h> -#include <comus/drivers/uart.h> - -void fputc(FILE *stream, char c) -{ - (void)stream; // TODO: manage stream - uart_out(c); - tty_out(c); -} diff --git a/kernel/lib/isdigit.c b/kernel/lib/isdigit.c new file mode 100644 index 0000000..f645093 --- /dev/null +++ b/kernel/lib/isdigit.c @@ -0,0 +1,6 @@ +#include <lib.h> + +int isdigit(int c) +{ + return c >= '0' && c <= '9'; +} diff --git a/kernel/lib/isspace.c b/kernel/lib/isspace.c new file mode 100644 index 0000000..5196d0c --- /dev/null +++ b/kernel/lib/isspace.c @@ -0,0 +1,16 @@ +#include <lib.h> + +int isspace(int c) +{ + switch (c) { + case ' ': + case '\t': + case '\v': + case '\f': + case '\r': + case '\n': + return 1; + default: + return 0; + } +} diff --git a/kernel/lib/itoc.c b/kernel/lib/itoc.c new file mode 100644 index 0000000..493b66e --- /dev/null +++ b/kernel/lib/itoc.c @@ -0,0 +1,10 @@ +#include <lib.h> + +char itoc(int i) +{ + if (i < 10) { + return '0' + i; + } else { + return 'a' + (i - 10); + } +} diff --git a/kernel/lib/kalloc.c b/kernel/lib/kalloc.c new file mode 100644 index 0000000..9845a62 --- /dev/null +++ b/kernel/lib/kalloc.c @@ -0,0 +1,210 @@ +#include <lib.h> +#include <comus/memory.h> + +#define MAGIC 0xBEEFCAFE + +struct page_header { + struct page_header *next; + struct page_header *prev; + size_t + node_number; // all headers on the same page alloc have the same node number (so they can be merged) + size_t + free; // free space after the node (if its the last node in the alloc block) + size_t used; // how much space this allocation is using + uint64_t magic; +}; + +static const size_t header_len = sizeof(struct page_header); +static struct page_header *start_header = NULL; +static struct page_header *end_header = NULL; + +static struct page_header *get_header(void *ptr) +{ + struct page_header *header = + (struct page_header *)((uintptr_t)ptr - header_len); + + // PERF: do we want to make sure this pointer is paged + // before reading it??? + if (header->magic != MAGIC) { + return NULL; // invalid pointer + } + + return header; +} + +static void *alloc_new(size_t size) +{ + size_t pages = ((size + header_len) / PAGE_SIZE) + 1; + + void *addr = kalloc_pages(pages); + void *mem = (char *)addr + header_len; + + size_t total = pages * PAGE_SIZE; + size_t free = total - (size + header_len); + + if (addr == NULL) { + return NULL; + } + + size_t node; + if (end_header != NULL) { + node = end_header->node_number + 1; + } else { + node = 0; + } + + struct page_header *header = addr; + header->magic = 0xBEEFCAFE; + header->used = size; + header->free = free; + header->prev = end_header; + header->next = NULL; + header->node_number = node; + + if (start_header == NULL) { + start_header = header; + } + + if (end_header != NULL) { + end_header->next = header; + } else { + end_header = header; + } + + return mem; +} + +static void *alloc_block(size_t size, struct page_header *block) +{ + struct page_header *header = + (struct page_header *)((char *)block + block->used + header_len); + + size_t free = block->free - (size + header_len); + block->free = 0; + + header->magic = MAGIC; + header->used = size; + header->free = free; + header->prev = block; + header->next = block->next; + block->next = header; + header->node_number = block->node_number; + + void *mem = (char *)header + header_len; + + return mem; +} + +void *kalloc(size_t size) +{ + struct page_header *header = start_header; + + for (; header != NULL; header = header->next) { + size_t free = header->free; + if (free < header_len) + continue; + if (size <= + (free - header_len)) { // we must be able to fit data + header + break; + } + } + + if (header != NULL) { + return alloc_block(size, header); + } else { + return alloc_new(size); + } +} + +void *krealloc(void *src, size_t dst_len) +{ + struct page_header *header; + size_t src_len; + void *dst; + + // realloc of 0 means free pointer + if (dst_len == 0) { + kfree(src); + return NULL; + } + + // NULL src means allocate ptr + if (src == NULL) { + dst = kalloc(dst_len); + return dst; + } + + header = get_header(src); + + if (header == NULL) + return NULL; + + src_len = header->used; + + if (src_len == 0) + return NULL; + + dst = kalloc(dst_len); + + if (dst == NULL) + return NULL; // allocation failed + + if (dst_len < src_len) + src_len = dst_len; + + memcpy(dst, src, src_len); + kfree(src); + + return dst; +} + +void kfree(void *ptr) +{ + struct page_header *header; + + if (ptr == NULL) + return; + + header = get_header(ptr); + + if (header == NULL) + return; + + header->free += header->used; + header->used = 0; + + struct page_header *neighbor; + + // merge left + for (neighbor = header->prev; neighbor != NULL; neighbor = neighbor->prev) { + if (neighbor->node_number != header->node_number) + break; + if (neighbor->used && header->used) + break; + neighbor->free += header->free + header_len; + neighbor->next = header->next; + header = neighbor; + } + + // merge right + for (neighbor = header->next; neighbor != NULL; neighbor = neighbor->next) { + if (neighbor->node_number != header->node_number) + break; + if (neighbor->used) + break; + header->free += neighbor->free + header_len; + header->next = neighbor->next; + } + + if ((header->next == NULL || + header->next->node_number != header->node_number) && + (header->prev == NULL || + header->prev->node_number != header->node_number) && + header->used == 0) { + if (header->next) + header->next->prev = header->prev; + if (header->prev) + header->prev->next = header->next; + kfree_pages(header); + } +} diff --git a/kernel/lib/kprintf.c b/kernel/lib/kprintf.c new file mode 100644 index 0000000..a76036f --- /dev/null +++ b/kernel/lib/kprintf.c @@ -0,0 +1,576 @@ +#include <lib.h> +#include <comus/drivers/uart.h> +#include <comus/drivers/tty.h> + +#define PRINTF_NUMERIC_BUF_LEN 50 + +typedef union { + unsigned long long int u; + signed long long int i; + char *str; + char c; +} data_t; + +/// options that can be set inside a specifier +/// flags, width, precision, length, and data type +typedef struct { + /* flags */ + /// left justify content + uint8_t left : 1; + /// force sign (+/-) on numeric output + uint8_t sign : 1; + /// leave space if no printed sign on numeric output + uint8_t space : 1; + /// preceed hex/octal output with '0x' + uint8_t hash : 1; + /// left pads numeric output with zeros + uint8_t zero : 1; + uint8_t : 3; + + /* width & precision */ + /// minimum number of characters to be printed (padding if origonal is less) + int width; + /// digit precision used when printing numerical answers + int precision; + /// if a fixed minimum width has been provided + uint8_t width_set : 1; + /// if the provided minimum width is in the next variable argument + uint8_t width_varies : 1; + /// if a fixed digit precision has been provided + uint8_t precision_set : 1; + /// if the provided digit precision is in the next variable argument + uint8_t precision_varies : 1; + uint8_t : 4; + + /* length */ + /// what size to read argument as + enum printf_len { + PRINTF_LEN_CHAR, + PRINTF_LEN_SHORT_INT, + PRINTF_LEN_INT, + PRINTF_LEN_LONG_INT, + PRINTF_LEN_LONG_LONG_INT, + PRINTF_LEN_SIZE_T, + } len; + + /* other */ + /// radix to print the numerical answers as + uint8_t radix; + /// case to print hexadecimal values as + bool is_uppercase; +} options_t; + +typedef struct { + /* input */ + /// the origonal format string + const char *format; + /// maximum allowed output length + size_t max_len; + /// if a maximum output length is set + bool has_max_len; + + /* output */ + size_t written_len; + bool sprintf; + char *sprintf_buf; + + /* pass 2 */ + char *output; +} context_t; + +static void printf_putc(context_t *ctx, char c) +{ + // bounds check + if (ctx->has_max_len) + if (ctx->written_len >= ctx->max_len) + return; + + // write to correct + if (ctx->sprintf) + *(ctx->sprintf_buf++) = c; + else + kputc(c); + + ctx->written_len++; +} + +static int parse_flag(const char **res, options_t *opts) +{ + const char *fmt = *res; + switch (*(fmt++)) { + case '-': + opts->left = 1; + break; + case '+': + opts->sign = 1; + break; + case ' ': + opts->space = 1; + break; + case '#': + opts->hash = 1; + break; + case '0': + opts->zero = 1; + break; + default: + return 0; + } + + *res = fmt; + return 1; +} + +static void parse_width(const char **res, options_t *opts) +{ + const char *fmt = *res; + char *end = NULL; + + // check varies + if (*fmt == '*') { + opts->width_varies = true; + *res = fmt++; + return; + } + + // parse num + long width = strtol(fmt, &end, 10); + if (end != NULL) { + opts->width_set = 1; + opts->width = width; + *res = end; + return; + } +} + +static void parse_precision(const char **res, options_t *opts) +{ + const char *fmt = *res; + char *end = NULL; + + // check for dot + if (*(fmt++) != '.') + return; + + // check varies + if (*fmt == '*') { + opts->precision_varies = true; + *res = fmt++; + return; + } + + // parse num + long precision = strtol(fmt, &end, 10); + if (end != NULL) { + opts->precision_set = 1; + opts->precision = precision; + *res = end; + return; + } +} + +static void parse_length(const char **res, options_t *opts) +{ + const char *fmt = *res; + + switch (*(fmt++)) { + // half + case 'h': + if (*fmt == 'h') { + opts->len = PRINTF_LEN_CHAR; + fmt++; + } else { + opts->len = PRINTF_LEN_SHORT_INT; + } + break; + // long + case 'l': + if (*fmt == 'l') { + opts->len = PRINTF_LEN_LONG_LONG_INT; + fmt++; + } else { + opts->len = PRINTF_LEN_LONG_INT; + } + break; + // size_t + case 'z': + opts->len = PRINTF_LEN_SIZE_T; + break; + default: + opts->len = PRINTF_LEN_INT; + return; + } + + *res = fmt; +} + +static void get_radix(char spec, options_t *opts) +{ + switch (spec) { + case 'x': + case 'X': + opts->radix = 16; + break; + case 'o': + opts->radix = 8; + break; + default: + opts->radix = 10; + break; + } +} + +static void get_case(char spec, options_t *opts) +{ + if (spec == 'X') + opts->is_uppercase = 1; +} + +static char printf_itoc(int uppercase, int i) +{ + // decimal + if (i < 10) { + return i + '0'; + } + // hex + if (uppercase) { + return (i - 10) + 'A'; + } else { + return (i - 10) + 'a'; + } +} + +static int printf_lltoa(char *buf, options_t *opts, bool is_neg, + unsigned long long int num) +{ + int precision = 0; + char *start = buf; + + // get width of number + int len = 0; + unsigned long long int temp = num; + if (temp == 0) + len = 1; + while (temp) { + if (opts->precision_set && precision++ >= opts->precision) + break; + temp /= opts->radix; + len++; + } + precision = 0; + + // sign + if (is_neg) { + *(buf++) = '-'; + } else if (opts->sign) { + *(buf++) = '+'; + } else if (opts->space) { + *(buf++) = ' '; + } + + // radix specifier + if (opts->hash) { + if (opts->radix == 8) { + *(buf++) = '0'; + *(buf++) = 'o'; + } + if (opts->radix == 16) { + *(buf++) = '0'; + *(buf++) = 'x'; + } + } + + // print zeros if needed + if (opts->width_set && len < opts->width && opts->zero) { + while (len++ < opts->width) + *(buf++) = '0'; + } + + // write number + if (num == 0) { + *(buf++) = '0'; + } + while (num) { + if (opts->precision_set && precision++ >= opts->precision) + break; + *(buf++) = printf_itoc(opts->is_uppercase, num % opts->radix); + num /= opts->radix; + } + *(buf++) = '\0'; + + return buf - start; +} + +static void handle_int_specifier(context_t *ctx, options_t *const opts, + bool has_sign_bit, data_t num) +{ + bool is_neg = false; + + // get sign if possible neg + if (has_sign_bit) { + if (num.i < 0) { + num.i = -num.i; + is_neg = true; + } + } + + // get length of number and number + char buf[PRINTF_NUMERIC_BUF_LEN]; + int buf_len = printf_lltoa(buf, opts, is_neg, num.u); + + // get needed padding + int padding = 0; + if (opts->width_set && (buf_len < opts->width)) + padding = opts->width - buf_len; + + /* print */ + // left padding + if (opts->left == 0) { + for (int i = 0; i < padding; i++) + printf_putc(ctx, opts->zero ? '0' : ' '); + } + // number + for (int i = 0; i < buf_len; i++) + printf_putc(ctx, buf[i]); + // right padding + if (opts->left == 1) { + for (int i = 0; i < padding; i++) + printf_putc(ctx, opts->zero ? '0' : ' '); + } +} + +static void handle_char_specifier(context_t *ctx, data_t c) +{ + printf_putc(ctx, c.c); +} + +static void handle_string_specifier(context_t *ctx, options_t *opts, + data_t data) +{ + char *str = data.str; + int str_len = 0; + + // get length of string + if (opts->precision_set) + str_len = opts->precision; + else + str_len = strlen(str); + + // get needed padding + int padding = 0; + if (opts->width_set && (str_len < opts->width)) + padding = opts->width - str_len; + + /* print */ + // left padding + if (opts->left == 0) { + for (int i = 0; i < padding; i++) + printf_putc(ctx, ' '); + } + // string + for (int i = 0; i < str_len; i++) + printf_putc(ctx, str[i]); + // right padding + if (opts->left == 1) { + for (int i = 0; i < padding; i++) + printf_putc(ctx, ' '); + } +} + +static void do_printf(context_t *ctx, va_list args) +{ + const char *fmt = ctx->format; + + char c; + while (c = *fmt++, c != '\0') { + // save start of fmt for current iteration + const char *start = fmt - 1; + + // ignore if not % + if (c != '%') { + printf_putc(ctx, c); + continue; + } + + // read opts + options_t opts = { 0 }; + while (parse_flag(&fmt, &opts)) + ; + parse_width(&fmt, &opts); + parse_precision(&fmt, &opts); + parse_length(&fmt, &opts); + + // read specifier + char spec = *fmt++; + get_radix(spec, &opts); + get_case(spec, &opts); + + // read varied width / precision + if (opts.width_varies) { + opts.width_set = 1; + opts.width = va_arg(args, int); + } + if (opts.precision_varies) { + opts.precision_set = 1; + opts.precision = va_arg(args, int); + } + // read data from args + data_t data; + switch (spec) { + case 'p': + opts.len = PRINTF_LEN_SIZE_T; + opts.width_set = true; + opts.radix = 16; + opts.hash = true; + opts.zero = true; + case 'd': + case 'i': + case 'u': + case 'o': + case 'x': + case 'X': + // read number from arg + switch (opts.len) { + case PRINTF_LEN_CHAR: + data.u = va_arg(args, unsigned int); // char + break; + case PRINTF_LEN_SHORT_INT: + data.u = va_arg(args, unsigned int); // short int + break; + case PRINTF_LEN_INT: + data.u = va_arg(args, unsigned int); + break; + case PRINTF_LEN_LONG_INT: + data.u = va_arg(args, unsigned long int); + break; + case PRINTF_LEN_LONG_LONG_INT: + data.u = va_arg(args, unsigned long long int); + break; + case PRINTF_LEN_SIZE_T: + data.u = va_arg(args, size_t); + break; + } + break; + // end int + case 's': + // read string + data.str = va_arg(args, void *); + break; + // end string + case 'c': + // read char + data.c = va_arg(args, int); + break; + // end char + } + + switch (spec) { + // signed int + case 'd': + case 'i': + handle_int_specifier(ctx, &opts, true, data); + break; + // unsigned int + case 'p': + case 'u': + case 'o': + case 'x': + case 'X': + handle_int_specifier(ctx, &opts, false, data); + break; + // character + case 'c': + handle_char_specifier(ctx, data); + break; + // string + case 's': + handle_string_specifier(ctx, &opts, data); + break; + // unknown + default: + // print from % to current + for (; start < fmt; start++) + printf_putc(ctx, *start); + break; + } + } +} + +void kprintf(const char *format, ...) +{ + va_list args; + va_start(args, format); + kvprintf(format, args); + va_end(args); +} + +size_t ksprintf(char *restrict s, const char *format, ...) +{ + va_list args; + size_t amt; + va_start(args, format); + amt = kvsprintf(s, format, args); + va_end(args); + return amt; +} + +size_t snprintf(char *restrict s, size_t maxlen, const char *format, ...) +{ + va_list args; + size_t amt; + va_start(args, format); + amt = kvsnprintf(s, maxlen, format, args); + va_end(args); + return amt; +} + +void kvprintf(const char *format, va_list args) +{ + // create context + context_t ctx = { 0 }; + ctx.format = format; + // print + do_printf(&ctx, args); +} + +size_t kvsprintf(char *restrict s, const char *format, va_list args) +{ + // create context + context_t ctx = { 0 }; + ctx.format = format; + // sprintf buffer + ctx.sprintf_buf = s; + ctx.sprintf = 1; + // print + do_printf(&ctx, args); + return ctx.written_len; +} + +size_t kvsnprintf(char *restrict s, size_t maxlen, const char *format, + va_list args) +{ + // create context + context_t ctx = { 0 }; + ctx.format = format; + // sprintf buffer + ctx.sprintf_buf = s; + ctx.sprintf = 1; + // sprintf max_len + ctx.has_max_len = 1; + ctx.max_len = maxlen; + // print + do_printf(&ctx, args); + return ctx.written_len; +} + +void kputc(char c) +{ + tty_out(c); + uart_out(c); +} + +void kputs(const char *str) +{ + tty_out_str(str); + uart_out_str(str); +} diff --git a/kernel/lib/memcmp.c b/kernel/lib/memcmp.c new file mode 100644 index 0000000..f938d0a --- /dev/null +++ b/kernel/lib/memcmp.c @@ -0,0 +1,9 @@ +#include <lib.h> + +int memcmp(const void *restrict vl, const void *restrict vr, size_t n) +{ + const unsigned char *l = vl, *r = vr; + for (; n && *l == *r; n--, l++, r++) + ; + return n ? *l - *r : 0; +} diff --git a/kernel/lib/memcpy.c b/kernel/lib/memcpy.c new file mode 100644 index 0000000..e848cef --- /dev/null +++ b/kernel/lib/memcpy.c @@ -0,0 +1,10 @@ +#include <lib.h> + +void *memcpy(void *restrict dest, const void *restrict src, size_t n) +{ + char *d = dest; + const char *s = src; + for (; n; n--) + *d++ = *s++; + return dest; +} diff --git a/kernel/lib/memcpyv.c b/kernel/lib/memcpyv.c new file mode 100644 index 0000000..bc95807 --- /dev/null +++ b/kernel/lib/memcpyv.c @@ -0,0 +1,11 @@ +#include <lib.h> + +volatile void *memcpyv(volatile void *restrict dest, + const volatile void *restrict src, size_t n) +{ + volatile char *d = dest; + volatile const char *s = src; + for (; n; n--) + *d++ = *s++; + return dest; +} diff --git a/kernel/lib/memmove.c b/kernel/lib/memmove.c new file mode 100644 index 0000000..55be66d --- /dev/null +++ b/kernel/lib/memmove.c @@ -0,0 +1,20 @@ +#include <lib.h> + +void *memmove(void *dest, const void *src, size_t n) +{ + char *d = dest; + const char *s = src; + + if (d == s) + return d; + + if (d < s) { + for (; n; n--) + *d++ = *s++; + } else { + while (n) + n--, d[n] = s[n]; + } + + return dest; +} diff --git a/kernel/lib/memmovev.c b/kernel/lib/memmovev.c new file mode 100644 index 0000000..56684a5 --- /dev/null +++ b/kernel/lib/memmovev.c @@ -0,0 +1,20 @@ +#include <lib.h> + +volatile void *memmovev(volatile void *dest, const volatile void *src, size_t n) +{ + volatile char *d = dest; + volatile const char *s = src; + + if (d == s) + return d; + + if (d < s) { + for (; n; n--) + *d++ = *s++; + } else { + while (n) + n--, d[n] = s[n]; + } + + return dest; +} diff --git a/kernel/lib/memset.c b/kernel/lib/memset.c new file mode 100644 index 0000000..d1c2a5e --- /dev/null +++ b/kernel/lib/memset.c @@ -0,0 +1,10 @@ +#include <lib.h> + +void *memset(void *dest, int c, size_t n) +{ + unsigned char *d = dest; + for (; n; n--) { + *d++ = c; + }; + return dest; +} diff --git a/kernel/lib/memsetv.c b/kernel/lib/memsetv.c new file mode 100644 index 0000000..647847f --- /dev/null +++ b/kernel/lib/memsetv.c @@ -0,0 +1,10 @@ +#include <lib.h> + +volatile void *memsetv(volatile void *dest, int c, size_t n) +{ + volatile unsigned char *d = dest; + for (; n; n--) { + *d++ = c; + }; + return dest; +} diff --git a/kernel/lib/panic.c b/kernel/lib/panic.c index 403418f..5381041 100644 --- a/kernel/lib/panic.c +++ b/kernel/lib/panic.c @@ -7,9 +7,9 @@ __attribute__((noreturn)) void panic(const char *format, ...) cli(); va_list list; va_start(list, format); - printf("\n\n!!! PANIC !!!\n"); - vprintf(format, list); - printf("\n\n"); + kprintf("\n\n!!! PANIC !!!\n"); + kvprintf(format, list); + kprintf("\n\n"); while (1) halt(); diff --git a/kernel/lib/stpcpy.c b/kernel/lib/stpcpy.c new file mode 100644 index 0000000..1a7c5bf --- /dev/null +++ b/kernel/lib/stpcpy.c @@ -0,0 +1,9 @@ +#include <lib.h> + +char *stpcpy(char *restrict dest, const char *restrict src) +{ + char *d = dest; + for (; (*d = *src); d++, src++) + ; + return d; +} diff --git a/kernel/lib/stpncpy.c b/kernel/lib/stpncpy.c new file mode 100644 index 0000000..87f9838 --- /dev/null +++ b/kernel/lib/stpncpy.c @@ -0,0 +1,10 @@ +#include <lib.h> + +char *stpncpy(char *restrict dest, const char *restrict src, size_t n) +{ + char *d = dest; + for (; (*d = *src) && n; d++, src++, n--) + ; + memset(d, 0, n); + return d; +} diff --git a/kernel/lib/strcat.c b/kernel/lib/strcat.c new file mode 100644 index 0000000..fcfa463 --- /dev/null +++ b/kernel/lib/strcat.c @@ -0,0 +1,7 @@ +#include <lib.h> + +char *strcat(char *restrict dest, const char *restrict src) +{ + strcpy(dest + strlen(dest), src); + return dest; +} diff --git a/kernel/lib/strcpy.c b/kernel/lib/strcpy.c new file mode 100644 index 0000000..d74e68d --- /dev/null +++ b/kernel/lib/strcpy.c @@ -0,0 +1,9 @@ +#include <lib.h> + +char *strcpy(char *restrict dest, const char *restrict src) +{ + char *d = dest; + for (; (*d = *src); d++, src++) + ; + return dest; +} diff --git a/kernel/lib/strlen.c b/kernel/lib/strlen.c new file mode 100644 index 0000000..6d31f2f --- /dev/null +++ b/kernel/lib/strlen.c @@ -0,0 +1,9 @@ +#include <lib.h> + +size_t strlen(const char *str) +{ + const char *p; + for (p = str; *p != 0; p++) { + } + return p - str; +} diff --git a/kernel/lib/strncmp.c b/kernel/lib/strncmp.c new file mode 100644 index 0000000..0cf5837 --- /dev/null +++ b/kernel/lib/strncmp.c @@ -0,0 +1,11 @@ +#include <lib.h> + +int strncmp(const char *restrict lhs, const char *restrict rhs, size_t n) +{ + const unsigned char *l = (void *)lhs, *r = (void *)rhs; + if (!n--) + return 0; + for (; *l && *r && n && *l == *r; l++, r++, n--) + ; + return *l - *r; +} diff --git a/kernel/lib/strncpy.c b/kernel/lib/strncpy.c new file mode 100644 index 0000000..f691191 --- /dev/null +++ b/kernel/lib/strncpy.c @@ -0,0 +1,10 @@ +#include <lib.h> + +char *strncpy(char *restrict dest, const char *restrict src, size_t n) +{ + char *d = dest; + for (; (*d = *src) && n; d++, src++, n--) + ; + memset(d, 0, n); + return dest; +} diff --git a/kernel/lib/strtoux.c b/kernel/lib/strtoux.c new file mode 100644 index 0000000..e8f828b --- /dev/null +++ b/kernel/lib/strtoux.c @@ -0,0 +1,43 @@ +#include <lib.h> + +#define STRTOUX(name, type) \ + type name(const char *restrict s, char **restrict endptr, int radix) \ + { \ + const char *s_start = s; \ + for (; isspace(*s); s++) \ + ; \ + \ + if ((radix == 0 || radix == 16) && \ + (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))) { \ + radix = 16; \ + s += 2; \ + } else if (radix == 0) { \ + if (*s == '0') { \ + radix = 8; \ + s++; \ + } else { \ + radix = 10; \ + } \ + } \ + \ + type num = 0; \ + int has_digit = 0; \ + \ + while (1) { \ + int n = ctoi(*s++); \ + if (n < 0 || n >= radix) \ + break; \ + has_digit = 1; \ + num = num * radix + n; \ + } \ + \ + if (endptr != NULL) { \ + *endptr = has_digit ? (char *)(s - 1) : (char *)s_start; \ + } \ + \ + return num; \ + } + +STRTOUX(strtoui, unsigned int) +STRTOUX(strtoul, unsigned long int) +STRTOUX(strtoull, unsigned long long int) diff --git a/kernel/lib/strtox.c b/kernel/lib/strtox.c new file mode 100644 index 0000000..620b8d3 --- /dev/null +++ b/kernel/lib/strtox.c @@ -0,0 +1,52 @@ +#include <lib.h> + +#define STRTOX(name, type) \ + type name(const char *restrict s, char **restrict endptr, int radix) \ + { \ + const char *s_start = s; \ + for (; isspace(*s); s++) \ + ; \ + \ + int sign = 0; \ + switch (*s) { \ + case '-': \ + sign = 1; /* fallthrough */ \ + case '+': \ + s++; \ + break; \ + } \ + \ + if ((radix == 0 || radix == 16) && \ + (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))) { \ + radix = 16; \ + s += 2; \ + } else if (radix == 0) { \ + if (*s == '0') { \ + radix = 8; \ + s++; \ + } else { \ + radix = 10; \ + } \ + } \ + \ + type num = 0; \ + int has_digit = 0; \ + \ + while (1) { \ + int n = ctoi(*s++); \ + if (n < 0 || n >= radix) \ + break; \ + has_digit = 1; \ + num = num * radix + n; \ + } \ + \ + if (endptr != NULL) { \ + *endptr = has_digit ? (char *)(s - 1) : (char *)s_start; \ + } \ + \ + return sign ? -num : num; \ + } + +STRTOX(strtoi, int) +STRTOX(strtol, long int) +STRTOX(strtoll, long long int) diff --git a/kernel/lib/uxtoa.c b/kernel/lib/uxtoa.c new file mode 100644 index 0000000..9133d29 --- /dev/null +++ b/kernel/lib/uxtoa.c @@ -0,0 +1,27 @@ +#include <lib.h> + +#define UXTOA(type, name) \ + char *name(unsigned type n, char *buffer, int radix) \ + { \ + if (n == 0) { \ + buffer[0] = '0'; \ + buffer[1] = '\0'; \ + return buffer + 1; \ + } \ + char *start = buffer; \ + for (; n; n /= radix) { \ + *buffer++ = itoc(n % radix); \ + } \ + char *buf_end = buffer; \ + *buffer-- = '\0'; \ + while (buffer > start) { \ + char tmp = *start; \ + *start++ = *buffer; \ + *buffer-- = tmp; \ + } \ + return buf_end; \ + } + +UXTOA(int, utoa) +UXTOA(long int, ultoa) +UXTOA(long long int, ulltoa) diff --git a/kernel/lib/xtoa.c b/kernel/lib/xtoa.c new file mode 100644 index 0000000..bd3a367 --- /dev/null +++ b/kernel/lib/xtoa.c @@ -0,0 +1,31 @@ +#include <lib.h> + +#define XTOA(type, name) \ + char *name(type n, char *buffer, int radix) \ + { \ + if (n == 0) { \ + buffer[0] = '0'; \ + buffer[1] = '\0'; \ + return buffer + 1; \ + } \ + if (n < 0) { \ + *buffer++ = '-'; \ + n = -n; \ + } \ + char *start = buffer; \ + for (; n; n /= radix) { \ + *buffer++ = itoc(n % radix); \ + } \ + char *buf_end = buffer; \ + *buffer-- = '\0'; \ + while (buffer > start) { \ + char tmp = *start; \ + *start++ = *buffer; \ + *buffer-- = tmp; \ + } \ + return buf_end; \ + } + +XTOA(int, itoa) +XTOA(long int, ltoa) +XTOA(long long int, lltoa) |