separating: there will be libk and libc
This commit is contained in:
17
libk/ctype.c
Normal file
17
libk/ctype.c
Normal file
@@ -0,0 +1,17 @@
|
||||
// Ctype implementation for blankos/libk
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
bool isdigit(char c)
|
||||
{
|
||||
return c >= '0' && c <= '9';
|
||||
}
|
||||
|
||||
bool isspace(char c)
|
||||
{
|
||||
return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r';
|
||||
}
|
||||
14
libk/ctype.h
Normal file
14
libk/ctype.h
Normal file
@@ -0,0 +1,14 @@
|
||||
// Ctype implementation for blankos/libk header
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#ifndef CTYPE_H
|
||||
#define CTYPE_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool isdigit(char c);
|
||||
bool isspace(char c);
|
||||
|
||||
#endif
|
||||
757
libk/stdio.c
Normal file
757
libk/stdio.c
Normal file
@@ -0,0 +1,757 @@
|
||||
// Standard input/output implementation for blankos/libk
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#include "../kernel/io.h"
|
||||
#include "stdio.h"
|
||||
#include "string.h"
|
||||
#include <stdint.h>
|
||||
#include "../kernel/system.h"
|
||||
#include "../drivers/framebuffer.h"
|
||||
#include "../drivers/serial.h"
|
||||
|
||||
extern uint32_t* framebuffer;
|
||||
extern uint32_t VGA_WIDTH;
|
||||
extern uint32_t VGA_HEIGHT;
|
||||
unsigned int VGA_X = 0, VGA_Y = 0;
|
||||
|
||||
extern int scanline;
|
||||
|
||||
int get_cursor_x()
|
||||
{
|
||||
return VGA_X;
|
||||
}
|
||||
|
||||
int get_cursor_y()
|
||||
{
|
||||
return VGA_Y;
|
||||
}
|
||||
|
||||
void draw_cursor(uint32_t color)
|
||||
{
|
||||
for (int y=12; y<CURSOR_HEIGHT; y++)
|
||||
{
|
||||
for (int x=0; x<CURSOR_WIDTH; x++)
|
||||
{
|
||||
putpixel(framebuffer, scanline, 32, VGA_X * CURSOR_WIDTH + x, VGA_Y * CURSOR_HEIGHT + y, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void draw_pixel(int x, int y, uint32_t color) //high level wrapper for putpixel
|
||||
{
|
||||
putpixel(framebuffer, scanline, 32, x, y, color);
|
||||
}
|
||||
|
||||
void draw_square(int x, int y, uint32_t color, int size)
|
||||
{
|
||||
int startx = x*size;
|
||||
int starty = y*size;
|
||||
|
||||
for (int i=0; i<size; i++)
|
||||
{
|
||||
for (int j=0; j<size; j++)
|
||||
{
|
||||
draw_pixel(startx+i, starty+j, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void erase_cursor()
|
||||
{
|
||||
draw_cursor(black);
|
||||
}
|
||||
|
||||
void move_cursor(int x, int y)
|
||||
{
|
||||
erase_cursor();
|
||||
VGA_X = x;
|
||||
VGA_Y = y;
|
||||
draw_cursor(white);
|
||||
}
|
||||
|
||||
// stdio wrapper for draw_char in graphics mode
|
||||
void putchar(unsigned short int c, int x, int y, uint32_t fg, uint32_t bg)
|
||||
{
|
||||
draw_char(c, x, y, fg, bg);
|
||||
}
|
||||
|
||||
void clear(void)
|
||||
{
|
||||
for (unsigned int y=0; y<VGA_HEIGHT; y++)
|
||||
{
|
||||
for (unsigned int x=0; x<VGA_WIDTH; x++)
|
||||
{
|
||||
putchar(' ', x, y, black, black);
|
||||
}
|
||||
}
|
||||
move_cursor(0, 0);
|
||||
}
|
||||
|
||||
void putc(char c)
|
||||
{
|
||||
erase_cursor();
|
||||
switch(c)
|
||||
{
|
||||
case '\n':
|
||||
VGA_X = 0;
|
||||
VGA_Y++;
|
||||
break;
|
||||
case '\r':
|
||||
VGA_X = 0;
|
||||
break;
|
||||
case '\t':
|
||||
VGA_X += 4;
|
||||
if (VGA_X >= VGA_WIDTH) {
|
||||
VGA_X -= VGA_WIDTH;
|
||||
VGA_Y++;
|
||||
}
|
||||
break;
|
||||
case '\b':
|
||||
if (VGA_X > 0)
|
||||
{
|
||||
VGA_X--;
|
||||
}
|
||||
else if (VGA_Y > 0) {
|
||||
VGA_Y--;
|
||||
VGA_X = VGA_WIDTH-1;
|
||||
}
|
||||
putchar(' ', VGA_X, VGA_Y, white, black);
|
||||
break;
|
||||
default:
|
||||
putchar(c, VGA_X, VGA_Y, white, black);
|
||||
VGA_X++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (VGA_X >= VGA_WIDTH)
|
||||
{
|
||||
VGA_Y++;
|
||||
VGA_X = 0;
|
||||
}
|
||||
if (VGA_Y >= VGA_HEIGHT)
|
||||
{
|
||||
serial_printf(3, "VGA_Y=%d, VGA_HEIGHT=%d: Scrolling...\r", VGA_Y, VGA_HEIGHT);
|
||||
scroll();
|
||||
VGA_Y = VGA_HEIGHT - 1;
|
||||
}
|
||||
|
||||
move_cursor(VGA_X, VGA_Y);
|
||||
}
|
||||
|
||||
void colorputc(char c, uint32_t fg, uint32_t bg)
|
||||
{
|
||||
erase_cursor();
|
||||
switch(c)
|
||||
{
|
||||
case '\n':
|
||||
VGA_X = 0;
|
||||
VGA_Y++;
|
||||
break;
|
||||
case '\r':
|
||||
VGA_X = 0;
|
||||
break;
|
||||
case '\t':
|
||||
VGA_X += 4;
|
||||
break;
|
||||
default:
|
||||
putchar(c, VGA_X, VGA_Y, fg, bg);
|
||||
VGA_X++;
|
||||
break;
|
||||
}
|
||||
|
||||
if (VGA_X >= VGA_WIDTH)
|
||||
{
|
||||
VGA_Y++;
|
||||
VGA_X = 0;
|
||||
}
|
||||
|
||||
if (VGA_Y >= VGA_HEIGHT)
|
||||
{
|
||||
serial_printf(3, "VGA_Y=%d, VGA_HEIGHT=%d: Scrolling...\r", VGA_Y, VGA_HEIGHT);
|
||||
scroll();
|
||||
VGA_Y = VGA_HEIGHT - 1;
|
||||
}
|
||||
|
||||
move_cursor(VGA_X, VGA_Y);
|
||||
}
|
||||
|
||||
void puts(const char* str)
|
||||
{
|
||||
while (*str)
|
||||
{
|
||||
putc(*str);
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
void colorputs(const char* str, uint32_t fg, uint32_t bg)
|
||||
{
|
||||
while (*str)
|
||||
{
|
||||
colorputc(*str, fg, bg);
|
||||
str++;
|
||||
}
|
||||
}
|
||||
|
||||
// double to string for printf
|
||||
void dtostrf(double val, char *buffer, int precision)
|
||||
{
|
||||
int whole_part = (int)val;
|
||||
double fractional_part = val - whole_part;
|
||||
if (fractional_part < 0) fractional_part = -fractional_part;
|
||||
|
||||
if (whole_part == 0)
|
||||
{
|
||||
*buffer++ = '0';
|
||||
}
|
||||
else
|
||||
{
|
||||
if (whole_part < 0)
|
||||
{
|
||||
*buffer++ = '-';
|
||||
whole_part = -whole_part;
|
||||
}
|
||||
char temp[32];
|
||||
int pos = 0;
|
||||
|
||||
while (whole_part > 0)
|
||||
{
|
||||
temp[pos++] = '0' + (whole_part % 10);
|
||||
whole_part /= 10;
|
||||
}
|
||||
while (pos > 0)
|
||||
{
|
||||
*buffer++ = temp[--pos];
|
||||
}
|
||||
}
|
||||
|
||||
*buffer++ = '.';
|
||||
for (int i = 0; i < precision; i++)
|
||||
{
|
||||
fractional_part *= 10;
|
||||
int digit = (int)fractional_part;
|
||||
*buffer++ = '0' + digit;
|
||||
fractional_part -= digit;
|
||||
}
|
||||
*buffer = '\0';
|
||||
}
|
||||
|
||||
void printf(const char* fmt, ...)
|
||||
{
|
||||
int* argp = (int*)&fmt;
|
||||
int state = PRINTF_STATE_START;
|
||||
int length = PRINTF_LENGTH_START;
|
||||
int radix = 10;
|
||||
bool sign = false;
|
||||
int width = 0;
|
||||
char pad_char = ' ';
|
||||
|
||||
argp++;
|
||||
while (*fmt)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case PRINTF_STATE_START:
|
||||
if (*fmt == '%')
|
||||
{
|
||||
state = PRINTF_STATE_LENGTH;
|
||||
width = 0;
|
||||
pad_char = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
putc(*fmt);
|
||||
}
|
||||
break;
|
||||
|
||||
case PRINTF_STATE_LENGTH:
|
||||
if (*fmt == '0')
|
||||
{
|
||||
pad_char = '0';
|
||||
state = PRINTF_STATE_WIDTH;
|
||||
}
|
||||
else if (*fmt >= '1' && *fmt <= '9')
|
||||
{
|
||||
width = *fmt - '0';
|
||||
state = PRINTF_STATE_WIDTH;
|
||||
}
|
||||
else if (*fmt == 'h')
|
||||
{
|
||||
length = PRINTF_LENGTH_SHORT;
|
||||
state = PRINTF_STATE_SHORT;
|
||||
}
|
||||
else if (*fmt == 'l')
|
||||
{
|
||||
length = PRINTF_LENGTH_LONG;
|
||||
state = PRINTF_STATE_LONG;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto PRINTF_STATE_SPEC_;
|
||||
}
|
||||
break;
|
||||
|
||||
case PRINTF_STATE_WIDTH:
|
||||
if (*fmt >= '0' && *fmt <= '9')
|
||||
{
|
||||
width = width * 10 + (*fmt - '0');
|
||||
}
|
||||
else
|
||||
{
|
||||
goto PRINTF_STATE_SPEC_;
|
||||
}
|
||||
break;
|
||||
|
||||
case PRINTF_STATE_SHORT:
|
||||
if (*fmt == 'h')
|
||||
{
|
||||
length = PRINTF_LENGTH_SHORT_SHORT;
|
||||
state = PRINTF_STATE_SPEC;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto PRINTF_STATE_SPEC_;
|
||||
}
|
||||
break;
|
||||
|
||||
case PRINTF_STATE_LONG:
|
||||
if (*fmt == 'l')
|
||||
{
|
||||
length = PRINTF_LENGTH_LONG_LONG;
|
||||
state = PRINTF_STATE_SPEC;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto PRINTF_STATE_SPEC_;
|
||||
}
|
||||
break;
|
||||
|
||||
case PRINTF_STATE_SPEC:
|
||||
PRINTF_STATE_SPEC_:
|
||||
switch (*fmt)
|
||||
{
|
||||
case 'c':
|
||||
putc((char)*argp);
|
||||
argp++;
|
||||
break;
|
||||
case 's':
|
||||
puts(*(const char**)argp);
|
||||
argp++;
|
||||
break;
|
||||
case '%':
|
||||
putc('%');
|
||||
break;
|
||||
case 'd':
|
||||
case 'i':
|
||||
radix = 10;
|
||||
sign = true;
|
||||
argp = printf_number(argp, length, sign, radix, width, pad_char);
|
||||
break;
|
||||
case 'u':
|
||||
radix = 10;
|
||||
sign = false;
|
||||
argp = printf_number(argp, length, sign, radix, width, pad_char);
|
||||
break;
|
||||
case 'X':
|
||||
case 'x':
|
||||
case 'p':
|
||||
radix = 16;
|
||||
sign = false;
|
||||
argp = printf_number(argp, length, sign, radix, width, pad_char);
|
||||
break;
|
||||
case 'o':
|
||||
radix = 8;
|
||||
sign = false;
|
||||
argp = printf_number(argp, length, sign, radix, width, pad_char);
|
||||
break;
|
||||
case 'f': {
|
||||
double* dargp = (double*)argp;
|
||||
double d = *(double*)dargp;
|
||||
char buffer[64];
|
||||
dtostrf(d, buffer, 6);
|
||||
puts(buffer);
|
||||
argp += 2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
state = PRINTF_STATE_START;
|
||||
length = PRINTF_LENGTH_START;
|
||||
radix = 10;
|
||||
sign = false;
|
||||
width = 0;
|
||||
pad_char = ' ';
|
||||
break;
|
||||
}
|
||||
fmt++;
|
||||
}
|
||||
}
|
||||
|
||||
const char charset[] = "0123456789abcdef";
|
||||
|
||||
int* printf_number(int* argp, int length, bool sign, int radix, int width, char pad_char)
|
||||
{
|
||||
char buffer[32];
|
||||
unsigned long long number;
|
||||
int number_sign = 1;
|
||||
int pos = 0;
|
||||
|
||||
switch (length)
|
||||
{
|
||||
case PRINTF_LENGTH_SHORT_SHORT:
|
||||
case PRINTF_LENGTH_SHORT:
|
||||
case PRINTF_LENGTH_START:
|
||||
if (sign)
|
||||
{
|
||||
int n = *argp;
|
||||
if (n < 0)
|
||||
{
|
||||
n = -n;
|
||||
number_sign = -1;
|
||||
}
|
||||
number = (unsigned long long)n;
|
||||
}
|
||||
else
|
||||
{
|
||||
number = *(unsigned int*)argp;
|
||||
}
|
||||
argp++;
|
||||
break;
|
||||
case PRINTF_LENGTH_LONG:
|
||||
if (sign)
|
||||
{
|
||||
long int n = *(long int*)argp;
|
||||
if (n < 0)
|
||||
{
|
||||
n = -n;
|
||||
number_sign = -1;
|
||||
}
|
||||
number = (unsigned long long)n;
|
||||
}
|
||||
else
|
||||
{
|
||||
number = *(unsigned long int*)argp;
|
||||
}
|
||||
argp += 2;
|
||||
break;
|
||||
case PRINTF_LENGTH_LONG_LONG:
|
||||
if (sign)
|
||||
{
|
||||
long long int n = *(long long int*)argp;
|
||||
if (n < 0)
|
||||
{
|
||||
n = -n;
|
||||
number_sign = -1;
|
||||
}
|
||||
number = (unsigned long long)n;
|
||||
}
|
||||
else
|
||||
{
|
||||
number = *(unsigned long long int*)argp;
|
||||
}
|
||||
argp += 4;
|
||||
break;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
uint32_t rem;
|
||||
x86_div64_32(number, radix, &number, &rem);
|
||||
buffer[pos++] = charset[rem];
|
||||
} while (number > 0);
|
||||
|
||||
if (sign && number_sign < 0)
|
||||
{
|
||||
buffer[pos++] = '-';
|
||||
}
|
||||
|
||||
int padding = width - pos;
|
||||
|
||||
while (padding-- > 0)
|
||||
{
|
||||
putc(pad_char);
|
||||
}
|
||||
|
||||
while (--pos >= 0)
|
||||
{
|
||||
putc(buffer[pos]);
|
||||
}
|
||||
|
||||
return argp;
|
||||
}
|
||||
/*
|
||||
int getch()
|
||||
{
|
||||
return keyboard_getchar();
|
||||
}
|
||||
|
||||
void get_input(char *buffer, int size) {
|
||||
int index = 0;
|
||||
char c;
|
||||
|
||||
while (index < size-1)
|
||||
{
|
||||
c = getch();
|
||||
if (c == '\n') {
|
||||
break;
|
||||
} else if (c == '\b') {
|
||||
if (index > 0) {
|
||||
index--;
|
||||
putc('\b');
|
||||
putc(' ');
|
||||
putc('\b');
|
||||
}
|
||||
} else {
|
||||
buffer[index++] = c;
|
||||
putc(c);
|
||||
}
|
||||
}
|
||||
buffer[index] = '\0';
|
||||
}
|
||||
*/
|
||||
|
||||
void colorprintf(uint32_t fg, uint32_t bg, const char* fmt, ...)
|
||||
{
|
||||
int* argp = (int*)&fmt;
|
||||
int state = PRINTF_STATE_START;
|
||||
int length = PRINTF_LENGTH_START;
|
||||
int radix = 10;
|
||||
bool sign = false;
|
||||
int width = 0;
|
||||
char pad_char = ' ';
|
||||
|
||||
argp++;
|
||||
while (*fmt)
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case PRINTF_STATE_START:
|
||||
if (*fmt == '%')
|
||||
{
|
||||
state = PRINTF_STATE_LENGTH;
|
||||
width = 0;
|
||||
pad_char = ' ';
|
||||
}
|
||||
else
|
||||
{
|
||||
colorputc(*fmt, fg, bg);
|
||||
}
|
||||
break;
|
||||
|
||||
case PRINTF_STATE_LENGTH:
|
||||
if (*fmt == '0')
|
||||
{
|
||||
pad_char = '0';
|
||||
state = PRINTF_STATE_WIDTH;
|
||||
}
|
||||
else if (*fmt >= '1' && *fmt <= '9')
|
||||
{
|
||||
width = *fmt - '0';
|
||||
state = PRINTF_STATE_WIDTH;
|
||||
}
|
||||
else if (*fmt == 'h')
|
||||
{
|
||||
length = PRINTF_LENGTH_SHORT;
|
||||
state = PRINTF_STATE_SHORT;
|
||||
}
|
||||
else if (*fmt == 'l')
|
||||
{
|
||||
length = PRINTF_LENGTH_LONG;
|
||||
state = PRINTF_STATE_LONG;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto PRINTF_STATE_SPEC_;
|
||||
}
|
||||
break;
|
||||
|
||||
case PRINTF_STATE_WIDTH:
|
||||
if (*fmt >= '0' && *fmt <= '9')
|
||||
{
|
||||
width = width * 10 + (*fmt - '0');
|
||||
}
|
||||
else
|
||||
{
|
||||
goto PRINTF_STATE_SPEC_;
|
||||
}
|
||||
break;
|
||||
|
||||
case PRINTF_STATE_SHORT:
|
||||
if (*fmt == 'h')
|
||||
{
|
||||
length = PRINTF_LENGTH_SHORT_SHORT;
|
||||
state = PRINTF_STATE_SPEC;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto PRINTF_STATE_SPEC_;
|
||||
}
|
||||
break;
|
||||
|
||||
case PRINTF_STATE_LONG:
|
||||
if (*fmt == 'l')
|
||||
{
|
||||
length = PRINTF_LENGTH_LONG_LONG;
|
||||
state = PRINTF_STATE_SPEC;
|
||||
}
|
||||
else
|
||||
{
|
||||
goto PRINTF_STATE_SPEC_;
|
||||
}
|
||||
break;
|
||||
|
||||
case PRINTF_STATE_SPEC:
|
||||
PRINTF_STATE_SPEC_:
|
||||
switch (*fmt)
|
||||
{
|
||||
case 'c':
|
||||
colorputc((char)*argp, fg, bg);
|
||||
argp++;
|
||||
break;
|
||||
case 's':
|
||||
colorputs(*(const char**)argp, fg, bg);
|
||||
argp++;
|
||||
break;
|
||||
case '%':
|
||||
putc('%');
|
||||
break;
|
||||
case 'd':
|
||||
case 'i':
|
||||
radix = 10;
|
||||
sign = true;
|
||||
argp = colorprintf_number(argp, length, sign, radix, width, pad_char, fg, bg);
|
||||
break;
|
||||
case 'u':
|
||||
radix = 10;
|
||||
sign = false;
|
||||
argp = colorprintf_number(argp, length, sign, radix, width, pad_char, fg, bg);
|
||||
break;
|
||||
case 'X':
|
||||
case 'x':
|
||||
case 'p':
|
||||
radix = 16;
|
||||
sign = false;
|
||||
argp = colorprintf_number(argp, length, sign, radix, width, pad_char, fg, bg);
|
||||
break;
|
||||
case 'o':
|
||||
radix = 8;
|
||||
sign = false;
|
||||
argp = colorprintf_number(argp, length, sign, radix, width, pad_char, fg, bg);
|
||||
break;
|
||||
case 'f': {
|
||||
double* dargp = (double*)argp;
|
||||
double d = *(double*)dargp;
|
||||
char buffer[64];
|
||||
dtostrf(d, buffer, 6);
|
||||
colorputs(buffer, fg, bg);
|
||||
argp += 2;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
state = PRINTF_STATE_START;
|
||||
length = PRINTF_LENGTH_START;
|
||||
radix = 10;
|
||||
sign = false;
|
||||
width = 0;
|
||||
pad_char = ' ';
|
||||
break;
|
||||
}
|
||||
fmt++;
|
||||
}
|
||||
}
|
||||
|
||||
int* colorprintf_number(int* argp, int length, bool sign, int radix, int width, char pad_char, uint32_t fg, uint32_t bg)
|
||||
{
|
||||
char buffer[32];
|
||||
unsigned long long number;
|
||||
int number_sign = 1;
|
||||
int pos = 0;
|
||||
|
||||
switch (length)
|
||||
{
|
||||
case PRINTF_LENGTH_SHORT_SHORT:
|
||||
case PRINTF_LENGTH_SHORT:
|
||||
case PRINTF_LENGTH_START:
|
||||
if (sign)
|
||||
{
|
||||
int n = *argp;
|
||||
if (n < 0)
|
||||
{
|
||||
n = -n;
|
||||
number_sign = -1;
|
||||
}
|
||||
number = (unsigned long long)n;
|
||||
}
|
||||
else
|
||||
{
|
||||
number = *(unsigned int*)argp;
|
||||
}
|
||||
argp++;
|
||||
break;
|
||||
case PRINTF_LENGTH_LONG:
|
||||
if (sign)
|
||||
{
|
||||
long int n = *(long int*)argp;
|
||||
if (n < 0)
|
||||
{
|
||||
n = -n;
|
||||
number_sign = -1;
|
||||
}
|
||||
number = (unsigned long long)n;
|
||||
}
|
||||
else
|
||||
{
|
||||
number = *(unsigned long int*)argp;
|
||||
}
|
||||
argp += 2;
|
||||
break;
|
||||
case PRINTF_LENGTH_LONG_LONG:
|
||||
if (sign)
|
||||
{
|
||||
long long int n = *(long long int*)argp;
|
||||
if (n < 0)
|
||||
{
|
||||
n = -n;
|
||||
number_sign = -1;
|
||||
}
|
||||
number = (unsigned long long)n;
|
||||
}
|
||||
else
|
||||
{
|
||||
number = *(unsigned long long int*)argp;
|
||||
}
|
||||
argp += 4;
|
||||
break;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
uint32_t rem;
|
||||
x86_div64_32(number, radix, &number, &rem);
|
||||
buffer[pos++] = charset[rem];
|
||||
} while (number > 0);
|
||||
|
||||
if (sign && number_sign < 0)
|
||||
{
|
||||
buffer[pos++] = '-';
|
||||
}
|
||||
|
||||
int padding = width - pos;
|
||||
|
||||
while (padding-- > 0)
|
||||
{
|
||||
colorputc(pad_char, fg, bg);
|
||||
}
|
||||
|
||||
while (--pos >= 0)
|
||||
{
|
||||
colorputc(buffer[pos], fg, bg);
|
||||
}
|
||||
|
||||
return argp;
|
||||
}
|
||||
97
libk/stdio.h
Normal file
97
libk/stdio.h
Normal file
@@ -0,0 +1,97 @@
|
||||
// Standard input/output implementation for blankos/libk header
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#ifndef STDIO_H
|
||||
#define STDIO_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define FB_GREEN 2
|
||||
#define FB_DARK_GREY 8
|
||||
|
||||
#define FB_CMD_PORT 0x3D4
|
||||
#define FB_DATA_PORT 0x3D5
|
||||
#define FB_HIGH_BYTE_CMD 14
|
||||
#define FB_LOW_BYTE_CMD 15
|
||||
|
||||
#define CURSOR_WIDTH 8
|
||||
#define CURSOR_HEIGHT 16
|
||||
|
||||
void draw_cursor(uint32_t color);
|
||||
void erase_cursor();
|
||||
void move_cursor(int x, int y);
|
||||
|
||||
void draw_pixel(int x, int y, uint32_t color);
|
||||
void draw_square(int x, int y, uint32_t color, int size);
|
||||
void putchar(unsigned short int c, int x, int y, uint32_t fg, uint32_t bg);
|
||||
void puts(const char* str);
|
||||
void clear(void);
|
||||
void colorputs(const char* str, uint32_t fg, uint32_t bg);
|
||||
void putcolor(int x, int y, unsigned int color);
|
||||
char getchar(int x, int y);
|
||||
unsigned int getcolor(int x, int y);
|
||||
void putc(char c);
|
||||
void colorputc(char c, uint32_t fg, uint32_t bg);
|
||||
void colorprintf(uint32_t fg, uint32_t bg, const char* fmt, ...);
|
||||
int* colorprintf_number(int* argp, int length, bool sign, int radix, int width, char pad_char, uint32_t fg, uint32_t bg);
|
||||
|
||||
#define PRINTF_STATE_START 0
|
||||
#define PRINTF_STATE_LENGTH 1
|
||||
#define PRINTF_STATE_SHORT 2
|
||||
#define PRINTF_STATE_LONG 3
|
||||
#define PRINTF_STATE_SPEC 4
|
||||
#define PRINTF_STATE_WIDTH 5
|
||||
|
||||
#define PRINTF_LENGTH_START 0
|
||||
#define PRINTF_LENGTH_SHORT_SHORT 1
|
||||
#define PRINTF_LENGTH_SHORT 2
|
||||
#define PRINTF_LENGTH_LONG 3
|
||||
#define PRINTF_LENGTH_LONG_LONG 4
|
||||
|
||||
void printf(const char* fmt, ...);
|
||||
int* printf_number(int* argp, int length, bool sign, int radix, int width, char pad_char);
|
||||
int getch();
|
||||
void get_input(char *buffer, int size);
|
||||
void dtostrf(double val, char *buffer, int precision);
|
||||
|
||||
enum Colors
|
||||
{
|
||||
// AARRGGBB?
|
||||
white = 0xFFFFFFFF,
|
||||
black = 0x00000000,
|
||||
red = 0x00FF0000,
|
||||
green = 0x0000FF00,
|
||||
blue = 0x000000FF,
|
||||
yellow = 0x00FFFF00,
|
||||
cyan = 0x0000FFFF,
|
||||
magenta = 0x00FF00FF,
|
||||
orange = 0x00FFA500,
|
||||
purple = 0x00800080,
|
||||
brown = 0x00A52A2A,
|
||||
gray = 0x00808080,
|
||||
pink = 0x00FFC0CB,
|
||||
lime = 0x00BFFF00,
|
||||
navy = 0x00000080,
|
||||
teal = 0x00008080,
|
||||
maroon = 0x00800000,
|
||||
olive = 0x00808000,
|
||||
silver = 0x00C0C0C0,
|
||||
gold = 0x00FFD700,
|
||||
indigo = 0x004B0082,
|
||||
violet = 0x00EE82EE,
|
||||
coral = 0x00FF7F50,
|
||||
turquoise = 0x0040E0D0,
|
||||
salmon = 0x00FA8072,
|
||||
chocolate = 0x00D2691E,
|
||||
khaki = 0x00F0E68C,
|
||||
lavender = 0x00E6E6FA,
|
||||
beige = 0x00F5F5DC
|
||||
};
|
||||
|
||||
int get_cursor_x();
|
||||
int get_cursor_y();
|
||||
|
||||
#endif
|
||||
134
libk/string.c
Normal file
134
libk/string.c
Normal file
@@ -0,0 +1,134 @@
|
||||
// String operations implementation for blankos/libk
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#include <stdint.h>
|
||||
#include "../kernel/system.h"
|
||||
|
||||
int strlen(const char* str)
|
||||
{
|
||||
int len = 0;
|
||||
while (*str++)
|
||||
{
|
||||
len++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int strcmp(const char* str1, const char* str2)
|
||||
{
|
||||
while (*str1 && (*str1 == *str2))
|
||||
{
|
||||
str1++;
|
||||
str2++;
|
||||
}
|
||||
return *(const unsigned char*)str1 - *(const unsigned char*)str2;
|
||||
}
|
||||
|
||||
char* strchr(const char* str, int c)
|
||||
{
|
||||
while (*str)
|
||||
{
|
||||
if (*str == (char)c)
|
||||
{
|
||||
return (char*)str;
|
||||
}
|
||||
str++;
|
||||
}
|
||||
if (c == '\0')
|
||||
{
|
||||
return (char*)str;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* strtok(char* str, const char* delimiter)
|
||||
{
|
||||
static char* last;
|
||||
if (str)
|
||||
{
|
||||
last = str;
|
||||
} else {
|
||||
str = last;
|
||||
}
|
||||
|
||||
if (!str || *str == '\0')
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* token_start = str;
|
||||
while (*str && !strchr(delimiter, *str))
|
||||
{
|
||||
str++;
|
||||
}
|
||||
|
||||
if (*str)
|
||||
{
|
||||
*str = '\0';
|
||||
last = str + 1;
|
||||
} else {
|
||||
last = NULL;
|
||||
}
|
||||
|
||||
return token_start;
|
||||
}
|
||||
|
||||
int atoi(char* str)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
for (int i=0; str[i] != '\0'; i++)
|
||||
{
|
||||
result = result*10 + str[i] - '0';
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void strcat(char* dest, const char* src)
|
||||
{
|
||||
while (*dest)
|
||||
{
|
||||
dest++;
|
||||
}
|
||||
|
||||
while (*src)
|
||||
{
|
||||
*dest = *src;
|
||||
dest++;
|
||||
src++;
|
||||
}
|
||||
|
||||
*dest = '\0';
|
||||
}
|
||||
|
||||
size_t strnlen(const char* str, size_t max_len)
|
||||
{
|
||||
size_t len = 0;
|
||||
while (*str && len < max_len)
|
||||
{
|
||||
len++;
|
||||
str++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
void strncat(char* dest, const char* src, size_t n)
|
||||
{
|
||||
while (*dest)
|
||||
{
|
||||
dest++;
|
||||
}
|
||||
|
||||
while (*src && n > 0)
|
||||
{
|
||||
*dest = *src;
|
||||
dest++;
|
||||
src++;
|
||||
n--;
|
||||
}
|
||||
|
||||
*dest = '\0';
|
||||
}
|
||||
21
libk/string.h
Normal file
21
libk/string.h
Normal file
@@ -0,0 +1,21 @@
|
||||
// String operations implementation for blankos/libk header
|
||||
// Author: xamidev
|
||||
// Licensed under the Unlicense. See the repo below.
|
||||
// https://github.com/xamidev/blankos
|
||||
|
||||
#ifndef STRING_H
|
||||
#define STRING_H
|
||||
|
||||
#include "../kernel/system.h"
|
||||
|
||||
int strlen(const char* str);
|
||||
int strcmp(const char* str1, const char* str2);
|
||||
char* strtok(char* str, const char* delimiter);
|
||||
int atoi(char* str);
|
||||
void strcat(char* dest, const char* src);
|
||||
|
||||
// Safer functions
|
||||
size_t strnlen(const char* str, size_t max_len);
|
||||
void strncat(char* dest, const char* src, size_t n);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user