579 lines
14 KiB
C
579 lines
14 KiB
C
|
#include "../include/common.h"
|
||
|
#include "../include/vga.h"
|
||
|
#include "../include/memory.h"
|
||
|
#include "../include/io.h"
|
||
|
|
||
|
static char num_str_buf[BUF_SIZE];
|
||
|
|
||
|
int sprintf(char *buf, const char *fmt, ...) {
|
||
|
va_list args;
|
||
|
int retval;
|
||
|
va_start(args, fmt);
|
||
|
retval = vsprintf(buf, fmt, args);
|
||
|
va_end(args);
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
size_t strlen(const char *str) {
|
||
|
size_t len = 0;
|
||
|
while (str[len])
|
||
|
len++;
|
||
|
return len;
|
||
|
}
|
||
|
|
||
|
int strcmp(const char *s1, const char *s2) {
|
||
|
char is_equal = 1;
|
||
|
|
||
|
for (; (*s1 != '\0') && (*s2 != '\0'); s1++, s2++) {
|
||
|
if (*s1 != *s2) {
|
||
|
is_equal = 0;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (is_equal) {
|
||
|
if (*s1 != '\0') {
|
||
|
return 1;
|
||
|
} else if (*s2 != '\0') {
|
||
|
return -1;
|
||
|
} else {
|
||
|
return 0;
|
||
|
}
|
||
|
} else {
|
||
|
return (int) (*s1 - *s2);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
char *strcpy(char *dest, const char *src) {
|
||
|
do {
|
||
|
*dest++ = *src++;
|
||
|
} while (*src != 0);
|
||
|
}
|
||
|
|
||
|
char *strcat(char *dest, const char *src) {
|
||
|
char *temp = dest;
|
||
|
while (*temp != '\0')
|
||
|
temp++;
|
||
|
while ((*temp++ = *src++) != '\0');
|
||
|
}
|
||
|
|
||
|
int isspace(int c) {
|
||
|
return (c == ' ' || c == '\t' || c == '\n' || c == '\r' || c == '\f' ||
|
||
|
c == '\v');
|
||
|
}
|
||
|
|
||
|
// isdigit
|
||
|
int isdigit(int c) {
|
||
|
return (c >= '0' && c <= '9');
|
||
|
}
|
||
|
|
||
|
// isalpha
|
||
|
int isalpha(int c) {
|
||
|
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
|
||
|
}
|
||
|
|
||
|
// isupper
|
||
|
int isupper(int c) {
|
||
|
return (c >= 'A' && c <= 'Z');
|
||
|
}
|
||
|
|
||
|
char *int32_to_str_dec(int32_t num, int flag, int width) {
|
||
|
int32_t num_tmp = num;
|
||
|
char *p = num_str_buf;
|
||
|
char *q = NULL;
|
||
|
int len = 0;
|
||
|
char *str_first = NULL;
|
||
|
char *str_end = NULL;
|
||
|
char ch = 0;
|
||
|
|
||
|
memset(num_str_buf, 0, sizeof(num_str_buf));
|
||
|
|
||
|
char dic[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
|
||
|
|
||
|
if (num_tmp < 0) {
|
||
|
*p++ = '-';
|
||
|
} else if (flag & FLAG_SIGN) {
|
||
|
*p++ = '+';
|
||
|
} else {
|
||
|
*p++ = ' ';
|
||
|
}
|
||
|
str_first = num_str_buf;
|
||
|
|
||
|
if (num_tmp >= 0 && !(flag & FLAG_SIGN)) {
|
||
|
str_first++;
|
||
|
}
|
||
|
|
||
|
if (num_tmp == 0) {
|
||
|
*p++ = '0';
|
||
|
} else {
|
||
|
if (num_tmp < 0)
|
||
|
num_tmp = -num_tmp;
|
||
|
|
||
|
while (num_tmp) {
|
||
|
*p++ = dic[num_tmp % 10];
|
||
|
num_tmp /= 10;
|
||
|
}
|
||
|
}
|
||
|
*p = '\0';
|
||
|
|
||
|
str_end = p;
|
||
|
len = str_end - str_first;
|
||
|
|
||
|
q = num_str_buf + 1;
|
||
|
p--;
|
||
|
while (q < p) {
|
||
|
ch = *q;
|
||
|
*q = *p;
|
||
|
*p = ch;
|
||
|
p--;
|
||
|
q++;
|
||
|
}
|
||
|
|
||
|
if (len < width) {
|
||
|
p = str_end;
|
||
|
|
||
|
if (flag & FLAG_LEFT_ADJUST) {
|
||
|
for (int i = 0; i < width - len; i++)
|
||
|
*p++ = ' ';
|
||
|
*p = '\0';
|
||
|
str_end = p;
|
||
|
} else {
|
||
|
while (p >= str_first) {
|
||
|
*(p + width - len) = *p;
|
||
|
p--;
|
||
|
}
|
||
|
|
||
|
if (flag & FLAG_ZERO_PAD) {
|
||
|
for (int i = 0; i < width - len; i++) {
|
||
|
num_str_buf[i + 1] = '0';
|
||
|
}
|
||
|
} else {
|
||
|
for (int i = 0; i < width - len; i++)
|
||
|
str_first[i] = ' ';
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return str_first;
|
||
|
}
|
||
|
|
||
|
char *int64_to_str_dec(int64_t num, int flag, int width) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
char *uint32_to_str_hex(uint32_t num, int flag, int width) {
|
||
|
uint32_t num_tmp = num;
|
||
|
char *p = num_str_buf;
|
||
|
char *q = NULL;
|
||
|
int len = 0;
|
||
|
char *str_first = NULL;
|
||
|
char *str_end = NULL;
|
||
|
char ch = 0;
|
||
|
|
||
|
memset(num_str_buf, 0, sizeof(num_str_buf));
|
||
|
|
||
|
char dic_lower[] = {'0', '1', '2', '3', '4', '5', '6', '7',
|
||
|
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||
|
char dic_upper[] = {'0', '1', '2', '3', '4', '5', '6', '7',
|
||
|
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||
|
char *dic = (flag & FLAG_LOWER) ? dic_lower : dic_upper;
|
||
|
|
||
|
str_first = num_str_buf;
|
||
|
|
||
|
*p++ = '0';
|
||
|
*p++ = (flag & FLAG_LOWER) ? 'x' : 'X';
|
||
|
|
||
|
if (!(flag & FLAG_ALTNT_FORM)) {
|
||
|
str_first += 2;
|
||
|
}
|
||
|
|
||
|
do {
|
||
|
*p++ = dic[num_tmp % 16];
|
||
|
num_tmp /= 16;
|
||
|
} while (num_tmp);
|
||
|
*p = '\0';
|
||
|
|
||
|
str_end = p;
|
||
|
len = str_end - str_first;
|
||
|
|
||
|
q = num_str_buf + 2;
|
||
|
p--;
|
||
|
while (q < p) {
|
||
|
ch = *q;
|
||
|
*q = *p;
|
||
|
*p = ch;
|
||
|
p--;
|
||
|
q++;
|
||
|
}
|
||
|
|
||
|
if (len < width) {
|
||
|
p = str_end;
|
||
|
|
||
|
if (flag & FLAG_LEFT_ADJUST) {
|
||
|
for (int i = 0; i < width - len; i++)
|
||
|
*p++ = ' ';
|
||
|
*p = '\0';
|
||
|
str_end = p;
|
||
|
} else {
|
||
|
while (p >= str_first) {
|
||
|
*(p + width - len) = *p;
|
||
|
p--;
|
||
|
}
|
||
|
if (flag & FLAG_ALTNT_FORM)
|
||
|
str_first[1] = (flag & FLAG_LOWER) ? 'x' : 'X';
|
||
|
|
||
|
if (flag & FLAG_ZERO_PAD) {
|
||
|
for (int i = 0; i < width - len; i++) {
|
||
|
num_str_buf[i + 2] = '0';
|
||
|
}
|
||
|
} else {
|
||
|
for (int i = 0; i < width - len; i++)
|
||
|
str_first[i] = ' ';
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (num == 0 && flag & FLAG_ALTNT_FORM)
|
||
|
str_first[1] = '0';
|
||
|
|
||
|
return str_first;
|
||
|
}
|
||
|
|
||
|
char *uint64_to_str_hex(uint64_t num, int flag, int width) {
|
||
|
uint64_t num_tmp = num;
|
||
|
char *p = num_str_buf;
|
||
|
char *q = NULL;
|
||
|
int len = 0;
|
||
|
char *str_first = NULL;
|
||
|
char *str_end = NULL;
|
||
|
char ch = 0;
|
||
|
|
||
|
memset(num_str_buf, 0, sizeof(num_str_buf));
|
||
|
|
||
|
char dic_lower[] = {'0', '1', '2', '3', '4', '5', '6', '7',
|
||
|
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||
|
char dic_upper[] = {'0', '1', '2', '3', '4', '5', '6', '7',
|
||
|
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||
|
char *dic = (flag & FLAG_LOWER) ? dic_lower : dic_upper;
|
||
|
|
||
|
str_first = num_str_buf;
|
||
|
|
||
|
*p++ = '0';
|
||
|
*p++ = (flag & FLAG_LOWER) ? 'x' : 'X';
|
||
|
|
||
|
if (!(flag & FLAG_ALTNT_FORM)) {
|
||
|
str_first += 2;
|
||
|
}
|
||
|
|
||
|
while (num_tmp) {
|
||
|
*p++ = dic[num_tmp % 16];
|
||
|
num_tmp /= 16;
|
||
|
}
|
||
|
*p = '\0';
|
||
|
|
||
|
str_end = p;
|
||
|
len = str_end - str_first;
|
||
|
|
||
|
q = num_str_buf + 2;
|
||
|
p--;
|
||
|
while (q < p) {
|
||
|
ch = *q;
|
||
|
*q = *p;
|
||
|
*p = ch;
|
||
|
p--;
|
||
|
q++;
|
||
|
}
|
||
|
|
||
|
if (len < width) {
|
||
|
p = str_end;
|
||
|
|
||
|
while (p >= str_first) {
|
||
|
*(p + width - len) = *p;
|
||
|
p--;
|
||
|
}
|
||
|
|
||
|
if (flag & FLAG_ZERO_PAD) {
|
||
|
for (int i = 0; i < width - len; i++) {
|
||
|
num_str_buf[i + 2] = '0';
|
||
|
}
|
||
|
} else {
|
||
|
for (int i = 0; i < width - len; i++)
|
||
|
str_first[i] = ' ';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return str_first;
|
||
|
}
|
||
|
|
||
|
char *uint32_to_str_oct(uint32_t num, int flag, int width) {
|
||
|
uint32_t num_tmp = num;
|
||
|
char *p = num_str_buf;
|
||
|
char *q = NULL;
|
||
|
int len = 0;
|
||
|
char *str_first = NULL;
|
||
|
char *str_end = NULL;
|
||
|
char ch = 0;
|
||
|
|
||
|
memset(num_str_buf, 0, sizeof(num_str_buf));
|
||
|
|
||
|
char dic[] = {'0', '1', '2', '3', '4', '5', '6', '7'};
|
||
|
|
||
|
str_first = num_str_buf;
|
||
|
|
||
|
*p++ = '0';
|
||
|
|
||
|
if (!(flag & FLAG_ALTNT_FORM)) {
|
||
|
str_first += 1;
|
||
|
}
|
||
|
|
||
|
while (num_tmp) {
|
||
|
*p++ = dic[num_tmp % 8];
|
||
|
num_tmp /= 8;
|
||
|
}
|
||
|
*p = '\0';
|
||
|
|
||
|
str_end = p;
|
||
|
len = str_end - str_first;
|
||
|
|
||
|
q = num_str_buf + 1;
|
||
|
p--;
|
||
|
while (q < p) {
|
||
|
ch = *q;
|
||
|
*q = *p;
|
||
|
*p = ch;
|
||
|
p--;
|
||
|
q++;
|
||
|
}
|
||
|
|
||
|
if (len < width) {
|
||
|
p = str_end;
|
||
|
|
||
|
if (flag & FLAG_LEFT_ADJUST) {
|
||
|
for (int i = 0; i < width - len; i++)
|
||
|
*p++ = ' ';
|
||
|
*p = '\0';
|
||
|
str_end = p;
|
||
|
} else {
|
||
|
while (p >= str_first) {
|
||
|
*(p + width - len) = *p;
|
||
|
p--;
|
||
|
}
|
||
|
|
||
|
if (flag & FLAG_ZERO_PAD) {
|
||
|
for (int i = 0; i < width - len; i++) {
|
||
|
num_str_buf[i + 1] = '0';
|
||
|
}
|
||
|
} else {
|
||
|
for (int i = 0; i < width - len; i++)
|
||
|
str_first[i] = ' ';
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return str_first;
|
||
|
}
|
||
|
|
||
|
char *insert_str(char *buf, const char *str) {
|
||
|
char *p = buf;
|
||
|
|
||
|
while (*str) {
|
||
|
*p++ = *str++;
|
||
|
}
|
||
|
|
||
|
return p;
|
||
|
}
|
||
|
|
||
|
int vsprintf(char *buf, const char *fmt, va_list args) {
|
||
|
char *str = buf;
|
||
|
int flag = 0;
|
||
|
int int_type = INT_TYPE_INT;
|
||
|
int tot_width = 0;
|
||
|
int sub_width = 0;
|
||
|
char buf2[64] = {0};
|
||
|
char *s = NULL;
|
||
|
char ch = 0;
|
||
|
int8_t num_8 = 0;
|
||
|
uint8_t num_u8 = 0;
|
||
|
int16_t num_16 = 0;
|
||
|
uint16_t num_u16 = 0;
|
||
|
int32_t num_32 = 0;
|
||
|
uint32_t num_u32 = 0;
|
||
|
int64_t num_64 = 0;
|
||
|
uint64_t num_u64 = 0;
|
||
|
|
||
|
for (const char *p = fmt; *p; p++) {
|
||
|
if (*p != '%') {
|
||
|
*str++ = *p;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
flag = 0;
|
||
|
tot_width = 0;
|
||
|
sub_width = 0;
|
||
|
int_type = INT_TYPE_INT;
|
||
|
|
||
|
p++;
|
||
|
|
||
|
while (*p == FLAG_ALTNT_FORM_CH || *p == FLAG_ZERO_PAD_CH ||
|
||
|
*p == FLAG_LEFT_ADJUST_CH || *p == FLAG_SPACE_BEFORE_POS_NUM_CH ||
|
||
|
*p == FLAG_SIGN_CH) {
|
||
|
if (*p == FLAG_ALTNT_FORM_CH) {
|
||
|
flag |= FLAG_ALTNT_FORM;
|
||
|
} else if (*p == FLAG_ZERO_PAD_CH) {
|
||
|
flag |= FLAG_ZERO_PAD;
|
||
|
} else if (*p == FLAG_LEFT_ADJUST_CH) {
|
||
|
flag |= FLAG_LEFT_ADJUST;
|
||
|
flag &= ~FLAG_ZERO_PAD;
|
||
|
} else if (*p == FLAG_SPACE_BEFORE_POS_NUM_CH) {
|
||
|
flag |= FLAG_SPACE_BEFORE_POS_NUM;
|
||
|
} else if (*p == FLAG_SIGN_CH) {
|
||
|
flag |= FLAG_SIGN;
|
||
|
} else {
|
||
|
}
|
||
|
|
||
|
p++;
|
||
|
}
|
||
|
|
||
|
if (*p == '*') {
|
||
|
tot_width = va_arg(args,
|
||
|
int);
|
||
|
if (tot_width < 0)
|
||
|
tot_width = 0;
|
||
|
p++;
|
||
|
} else {
|
||
|
while (isdigit(*p)) {
|
||
|
tot_width = tot_width * 10 + *p - '0';
|
||
|
p++;
|
||
|
}
|
||
|
}
|
||
|
if (*p == '.') {
|
||
|
if (*p == '*') {
|
||
|
sub_width = va_arg(args,
|
||
|
int);
|
||
|
if (sub_width < 0)
|
||
|
sub_width = 0;
|
||
|
p++;
|
||
|
} else {
|
||
|
while (isdigit(*p)) {
|
||
|
sub_width = sub_width * 10 + *p - '0';
|
||
|
p++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
LOOP_switch:
|
||
|
switch (*p) {
|
||
|
case 'h':
|
||
|
p++;
|
||
|
if (int_type >= INT_TYPE_MIN) {
|
||
|
int_type >>= 1;
|
||
|
goto LOOP_switch;
|
||
|
} else {
|
||
|
*str++ = '%';
|
||
|
break;
|
||
|
}
|
||
|
case 'l':
|
||
|
p++;
|
||
|
if (int_type <= INT_TYPE_MAX) {
|
||
|
int_type <<= 1;
|
||
|
goto LOOP_switch;
|
||
|
} else {
|
||
|
*str++ = '%';
|
||
|
break;
|
||
|
}
|
||
|
case 's':
|
||
|
s = va_arg(args,
|
||
|
char *);
|
||
|
str = insert_str(str, s);
|
||
|
break;
|
||
|
case 'c':
|
||
|
ch = (char) (va_arg(args,
|
||
|
int) &
|
||
|
0xFF);
|
||
|
*str++ = ch;
|
||
|
break;
|
||
|
case 'd':
|
||
|
switch (int_type) {
|
||
|
case INT_TYPE_CHAR:
|
||
|
num_8 = (int8_t) va_arg(args, int32_t);
|
||
|
str = insert_str(str, int32_to_str_dec(num_8, flag, tot_width));
|
||
|
break;
|
||
|
case INT_TYPE_SHORT:
|
||
|
num_16 = (int16_t) va_arg(args, int32_t);
|
||
|
str = insert_str(str, int32_to_str_dec(num_16, flag, tot_width));
|
||
|
break;
|
||
|
case INT_TYPE_INT:
|
||
|
num_32 = va_arg(args, int32_t);
|
||
|
str = insert_str(str, int32_to_str_dec(num_32, flag, tot_width));
|
||
|
break;
|
||
|
case INT_TYPE_LONG:
|
||
|
num_64 = va_arg(args, int64_t);
|
||
|
str = insert_str(str, int64_to_str_dec(num_64, flag, tot_width));
|
||
|
break;
|
||
|
case INT_TYPE_LONG_LONG:
|
||
|
num_64 = va_arg(args, int64_t);
|
||
|
str = insert_str(str, int64_to_str_dec(num_64, flag, tot_width));
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
case 'x':
|
||
|
flag |= FLAG_LOWER;
|
||
|
case 'X':
|
||
|
switch (int_type) {
|
||
|
case INT_TYPE_CHAR:
|
||
|
num_u8 = (uint8_t)
|
||
|
va_arg(args, uint32_t);
|
||
|
str = insert_str(str, uint32_to_str_hex(num_u8, flag, tot_width));
|
||
|
break;
|
||
|
case INT_TYPE_SHORT:
|
||
|
num_u16 = (uint16_t)
|
||
|
va_arg(args, uint32_t);
|
||
|
str = insert_str(str, uint32_to_str_hex(num_u16, flag, tot_width));
|
||
|
break;
|
||
|
case INT_TYPE_INT:
|
||
|
num_u32 = va_arg(args, uint32_t);
|
||
|
str = insert_str(str, uint32_to_str_hex(num_u32, flag, tot_width));
|
||
|
break;
|
||
|
case INT_TYPE_LONG:
|
||
|
num_u64 = va_arg(args, uint64_t);
|
||
|
str = insert_str(str, uint64_to_str_hex(num_u64, flag, tot_width));
|
||
|
break;
|
||
|
case INT_TYPE_LONG_LONG:
|
||
|
num_u64 = va_arg(args, uint64_t);
|
||
|
str = insert_str(str, uint64_to_str_hex(num_u64, flag, tot_width));
|
||
|
break;
|
||
|
}
|
||
|
break;
|
||
|
case 'o':
|
||
|
num_u32 = va_arg(args, uint32_t);
|
||
|
str = insert_str(str, uint32_to_str_oct(num_u32, flag, tot_width));
|
||
|
break;
|
||
|
case '%':
|
||
|
*str++ = '%';
|
||
|
break;
|
||
|
default:
|
||
|
*str++ = '%';
|
||
|
*str++ = *p;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
*str = '\0';
|
||
|
|
||
|
return str - buf;
|
||
|
}
|
||
|
|
||
|
void assert(int b,char* message){
|
||
|
if(!b){
|
||
|
printf("[KERNEL-PANIC]: %s",message);
|
||
|
while (1) io_hlt();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void trim(char *s){
|
||
|
char *p = s;
|
||
|
int len = strlen(p);
|
||
|
while (isspace(p[len - 1])) p[--len] = 0;
|
||
|
while (*p && isspace(*p)) ++p,--len;
|
||
|
memmove(s,p,len+1);
|
||
|
}
|