217 lines
4.7 KiB
C
217 lines
4.7 KiB
C
#include "klibc.h"
|
|
#include "serial.h"
|
|
#include "vga.h"
|
|
|
|
int memcmp(const void *aptr, const void *bptr, size_t size)
|
|
{
|
|
const unsigned char *a = (const unsigned char *)aptr;
|
|
const unsigned char *b = (const unsigned char *)bptr;
|
|
for (size_t i = 0; i < size; i++) {
|
|
if (a[i] < b[i])
|
|
return -1;
|
|
else if (b[i] < a[i])
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void *memcpy(void *dst, const void *src, size_t n)
|
|
{
|
|
char *dstChar = dst;
|
|
const char *srcChar = src;
|
|
for (size_t i = 0; i < n; i++) {
|
|
*(dstChar++) = *(srcChar++);
|
|
}
|
|
return dst;
|
|
}
|
|
|
|
void *memset(void *src, int c, size_t n)
|
|
{
|
|
for (char *ptr = (char *)src; n > 0; n--, ptr++) {
|
|
*ptr = (char)c;
|
|
}
|
|
return src;
|
|
}
|
|
|
|
char *itoa(int value, char *str, int base)
|
|
{
|
|
char *rc;
|
|
char *ptr;
|
|
char *low;
|
|
// Check for supported base.
|
|
if (base < 2 || base > 36) {
|
|
*str = '\0';
|
|
return str;
|
|
}
|
|
rc = ptr = str;
|
|
// Set '-' for negative decimals.
|
|
if (value < 0 && base == 10) {
|
|
*ptr++ = '-';
|
|
}
|
|
// Remember where the numbers start.
|
|
low = ptr;
|
|
// The actual conversion.
|
|
do {
|
|
// Modulo is negative for negative value. This trick makes abs() unnecessary.
|
|
*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz"
|
|
[35 + value % base];
|
|
value /= base;
|
|
} while (value);
|
|
// Terminating the string.
|
|
*ptr-- = '\0';
|
|
// Invert the numbers.
|
|
while (low < ptr) {
|
|
char tmp = *low;
|
|
*low++ = *ptr;
|
|
*ptr-- = tmp;
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
/* K&R */
|
|
void reverse(char s[])
|
|
{
|
|
int c, i, j;
|
|
for (i = 0, j = strlen(s) - 1; i < j; i++, j--) {
|
|
c = s[i];
|
|
s[i] = s[j];
|
|
s[j] = c;
|
|
}
|
|
}
|
|
|
|
/* K&R */
|
|
int strlen(const char s[])
|
|
{
|
|
int i = 0;
|
|
while (s[i] != '\0')
|
|
++i;
|
|
return i;
|
|
}
|
|
|
|
/* K&R
|
|
* Returns <0 if s1<s2, 0 if s1==s2, >0 if s1>s2 */
|
|
int strcmp(const char s1[], const char s2[])
|
|
{
|
|
int i;
|
|
for (i = 0; s1[i] == s2[i]; i++) {
|
|
if (s1[i] == '\0')
|
|
return 0;
|
|
}
|
|
return s1[i] - s2[i];
|
|
}
|
|
|
|
unsigned int strnlen(const char *s, size_t count)
|
|
{
|
|
const char *sc;
|
|
|
|
for (sc = s; count-- && *sc != '\0'; ++sc)
|
|
/* nothing */ continue;
|
|
|
|
return sc - s;
|
|
}
|
|
|
|
char *strzcpy(register char *dst, register const char *src, register int len)
|
|
{
|
|
int i;
|
|
|
|
if (len <= 0)
|
|
return dst;
|
|
|
|
for (i = 0; i < len; i++) {
|
|
dst[i] = src[i];
|
|
if (src[i] == '\0')
|
|
return dst;
|
|
}
|
|
|
|
dst[len - 1] = '\0';
|
|
return dst;
|
|
}
|
|
|
|
void printf(const char *format, ...)
|
|
{
|
|
va_list ap;
|
|
va_start(ap, format);
|
|
vprintf(format, ap);
|
|
va_end(ap);
|
|
}
|
|
|
|
void puts(const char *str)
|
|
{
|
|
while (*str) {
|
|
putc(*(str++));
|
|
}
|
|
}
|
|
|
|
void putc(const char str)
|
|
{
|
|
VGAputc(str);
|
|
serialPutc(str);
|
|
}
|
|
|
|
void printInt(int integer)
|
|
{
|
|
char num[sizeof(int) * 3]; // int max is 2^(sizeof(int)*8) which is (2^3)^(sizeof(int)*8/3)
|
|
// = 8^(sizeof(int)*8/3) ~ 10^(sizeof(int)*8/3)
|
|
int i = 0, k = 0;
|
|
if (integer < 0) {
|
|
putc('-');
|
|
}
|
|
if (integer == 0) {
|
|
num[i++] = 0;
|
|
}
|
|
while (integer != 0) {
|
|
int digit = integer % 10;
|
|
num[i++] = (digit > 0) ? digit : -digit;
|
|
integer = integer / 10;
|
|
}
|
|
for (k = i - 1; k >= 0; k--) {
|
|
putc(num[k] + '0');
|
|
}
|
|
}
|
|
|
|
void vprintf(const char *format, va_list ap)
|
|
{
|
|
int i = 0;
|
|
while (format[i] != '\0') {
|
|
switch (format[i]) {
|
|
case '%':
|
|
switch (format[i + 1]) {
|
|
case 'i':
|
|
case 'd': {
|
|
int d = va_arg(ap, int);
|
|
printInt(d);
|
|
break;
|
|
}
|
|
case 'x': {
|
|
char val[sizeof(int) * 2];
|
|
int d = va_arg(ap, int);
|
|
itoa(d, val, 16);
|
|
puts(val);
|
|
break;
|
|
}
|
|
case 'c': {
|
|
int c = va_arg(ap, int);
|
|
putc((char)c);
|
|
break;
|
|
}
|
|
case 's': {
|
|
char *str = va_arg(ap, char *);
|
|
if (!str)
|
|
str = "[NULL STR]";
|
|
puts(str);
|
|
break;
|
|
}
|
|
case '%':
|
|
putc('%');
|
|
break;
|
|
}
|
|
i++;
|
|
break;
|
|
|
|
default:
|
|
putc(format[i]);
|
|
}
|
|
i++;
|
|
}
|
|
}
|