This commit is contained in:
alexvoste
2026-05-07 02:22:25 +03:00
commit 1a9fd27a31
226 changed files with 29188 additions and 0 deletions
+19
View File
@@ -0,0 +1,19 @@
#ifndef _CTYPE_H
#define _CTYPE_H
int isalnum(int c);
int isalpha(int c);
int isblank(int c);
int iscntrl(int c);
int isdigit(int c);
int isgraph(int c);
int islower(int c);
int isupper(int c);
int isprint(int c);
int ispunct(int c);
int isspace(int c);
int isxdigit(int c);
int tolower(int c);
int toupper(int c);
#endif
+62
View File
@@ -0,0 +1,62 @@
#ifndef _MATH_H
#define _MATH_H
#include <stdint.h>
int abs(int x);
double fabs(double x);
double pow(double base, double exp);
double pow10(int n);
int isinf(double x);
int isnan(double x);
static inline double floor(double x) {
int64_t i = (int64_t)x;
return (double)(i - (x < (double)i));
}
static inline double ceil(double x) {
int64_t i = (int64_t)x;
return (double)(i + (x > (double)i));
}
static inline double round(double x) {
return (x >= 0.0) ? floor(x + 0.5) : ceil(x - 0.5);
}
static inline double sqrt(double x) {
double result;
asm volatile ("sqrtsd %1, %0" : "=x"(result) : "x"(x));
return result;
}
static inline float sqrtf(float x) {
float result;
asm volatile ("sqrtss %1, %0" : "=x"(result) : "x"(x));
return result;
}
static inline double log2(double x) {
double result;
asm volatile (
"fld1\n\t"
"fld %1\n\t"
"fyl2x\n\t"
"fstp %0\n\t"
: "=m"(result) : "m"(x)
);
return result;
}
#define MIN(a, b) ({ __typeof__(a) _a = (a); __typeof__(b) _b = (b); _a < _b ? _a : _b; })
#define MAX(a, b) ({ __typeof__(a) _a = (a); __typeof__(b) _b = (b); _a > _b ? _a : _b; })
#define ALIGN_UP(x, align) (((x) + (align) - 1) & ~((align) - 1))
#define ALIGN_DOWN(x, align) ((x) & ~((align) - 1))
#define IS_POWER_OF_TWO(x) ((x) != 0 && (((x) & ((x) - 1)) == 0))
#define INFINITY (1.0/0.0)
#define NAN (0.0/0.0)
#endif
+44
View File
@@ -0,0 +1,44 @@
#ifndef _STDIO_H
#define _STDIO_H
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#define EOF (-1)
#define MAX_SCROLL_LINES 1000
int putchar(int c);
int puts(const char *str);
int printf(const char *format, ...);
int sprintf (char* restrict buf, const char* restrict fmt, ...);
int snprintf(char* restrict buf, size_t size, const char* restrict fmt, ...);
int vsprintf (char* restrict buf, const char* restrict fmt, va_list ap);
int vsnprintf(char* restrict buf, size_t size, const char* restrict fmt, va_list ap);
int vprintf(const char* restrict fmt, va_list ap);
int getchar(void);
int scanf (const char * restrict fmt, ...);
int vscanf(const char * restrict fmt, va_list ap);
int sscanf (const char * restrict str, const char * restrict fmt, ...);
int vsscanf(const char *str, const char *fmt, va_list ap);
extern uint32_t cursor_x;
extern uint32_t cursor_y;
extern uint32_t text_color;
extern uint32_t bg_color;
void scroll_screen(int lines);
uint32_t get_screen_width(void);
uint32_t get_screen_height(void);
void set_cursor_position(uint32_t x, uint32_t y);
void get_cursor_position(uint32_t *x, uint32_t *y);
void set_text_color(uint32_t color);
void clear_screen(void);
void scroll_up(int lines);
#endif
+30
View File
@@ -0,0 +1,30 @@
#ifndef _STDLIB_H
#define _STDLIB_H
#include <stddef.h>
#include <math.h>
char* itoa(int val, char* restrict str, int base);
long strtol (const char * restrict s, char ** restrict end, int base);
unsigned long strtoul (const char * restrict s, char ** restrict end, int base);
long long strtoll (const char * restrict s, char ** restrict end, int base);
unsigned long long strtoull(const char * restrict s, char ** restrict end, int base);
static inline int atoi(const char* s) { return (int)strtol (s, (char**)0, 10); }
static inline long atol(const char* s) { return strtol (s, (char**)0, 10); }
void* malloc (size_t size);
void* calloc (size_t nmemb, size_t size);
void* realloc(void* ptr, size_t size);
void free (void* ptr);
void* aligned_alloc(size_t alignment, size_t size);
void aligned_free (void* ptr);
static inline void abort(void) {
__asm__ volatile ("cli; hlt");
__builtin_unreachable();
}
#endif
+45
View File
@@ -0,0 +1,45 @@
#ifndef _STRING_H
#define _STRING_H
#include <stddef.h>
#include <stdint.h>
void* memcpy (void* restrict dst, const void* restrict src, size_t n);
void* memmove(void* dst, const void* src, size_t n);
void* memset (void* dst, int c, size_t n);
int memcmp (const void* a, const void* b, size_t n);
void *memchr(void *p, int val, size_t n);
void *rawmemchr(void *p, int c);
void* memset_explicit(void* dst, int c, size_t n);
size_t strlen (const char* s);
size_t strnlen(const char* s, size_t maxlen);
char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t n);
char *strcat(char *dest, const char *src);
char* strncat(char* restrict dst, const char* restrict src, size_t n);
int strcmp (const char* a, const char* b);
int strncmp(const char* a, const char* b, size_t n);
char* strchr (const char* s, int c);
char* strrchr(const char* s, int c);
char* strstr (const char* haystack, const char* needle);
char* strpbrk(const char* s, const char* accept);
size_t strspn (const char* s, const char* accept);
size_t strcspn(const char* s, const char* reject);
char *strtok(char *str, const char *delim);
long strtol (const char* restrict s, char** restrict end, int base);
unsigned long strtoul(const char* restrict s, char** restrict end, int base);
char* strdup(const char* s);
static inline void bzero(void* s, size_t n) {
memset(s, 0, n);
}
#endif
+7
View File
@@ -0,0 +1,7 @@
#include <ctype.h>
int isalnum(int c) {
return (c >= '0' && c <= '9') ||
(c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z');
}
+6
View File
@@ -0,0 +1,6 @@
#include <ctype.h>
int isalpha(int c) {
return (c >= 'A' && c <= 'Z') ||
(c >= 'a' && c <= 'z');
}
+5
View File
@@ -0,0 +1,5 @@
#include <ctype.h>
int isblank(int c) {
return c == ' ' || c == '\t';
}
+8
View File
@@ -0,0 +1,8 @@
#include <ctype.h>
int iscntrl(int c) {
return c == '\n' || c == '\t' ||
c == '\r' || c == '\b' ||
c == '\f' || c == '\a' ||
c == '\0';
}
+5
View File
@@ -0,0 +1,5 @@
#include <ctype.h>
int isdigit(int c) {
return c >= '0' && c <= '9';
}
+5
View File
@@ -0,0 +1,5 @@
#include <ctype.h>
int isgraph(int c) {
return c >= 33 && c <= 126;
}
+5
View File
@@ -0,0 +1,5 @@
#include <ctype.h>
int islower(int c) {
return c >= 'a' && c <= 'z';
}
+5
View File
@@ -0,0 +1,5 @@
#include <ctype.h>
int isprint(int c) {
return c >= 32 && c <= 126;
}
+8
View File
@@ -0,0 +1,8 @@
#include <ctype.h>
int ispunct(int c) {
return (c >= 33 && c <= 47) ||
(c >= 58 && c <= 64) ||
(c >= 91 && c <= 96) ||
(c >= 123 && c <= 126);
}
+6
View File
@@ -0,0 +1,6 @@
#include <ctype.h>
int isspace(int c) {
return c == ' ' || c == '\t' || c == '\n' ||
c == '\v' || c == '\f' || c == '\r';
}
+5
View File
@@ -0,0 +1,5 @@
#include <ctype.h>
int isupper(int c) {
return c >= 'A' && c <= 'Z';
}
+7
View File
@@ -0,0 +1,7 @@
#include <ctype.h>
int isxdigit(int c) {
return (c >= '0' && c <= '9') ||
(c >= 'A' && c <= 'F') ||
(c >= 'a' && c <= 'f');
}
+8
View File
@@ -0,0 +1,8 @@
#include <ctype.h>
int tolower(int c) {
if (!isalpha(c))
return c;
return c + ('a' - 'A');
}
+8
View File
@@ -0,0 +1,8 @@
#include <ctype.h>
int toupper(int c) {
if (!isalpha(c))
return c;
return c - ('a' - 'A');
}
+5
View File
@@ -0,0 +1,5 @@
#include <math.h>
int abs(int n) {
return n >= 0 ? n : -n;
}
+12
View File
@@ -0,0 +1,12 @@
#include <math.h>
#include <stdint.h>
double fabs(double x) {
union {
double d;
uint64_t i;
} u = { .d = x };
u.i &= 0x7FFFFFFFFFFFFFFFULL;
return u.d;
}
+14
View File
@@ -0,0 +1,14 @@
#include <math.h>
#include <stdint.h>
int isinf(double x) {
union {
double f;
uint64_t i;
} u = { .f = x };
uint64_t exp = (u.i >> 52) & 0x7FF;
uint64_t mantissa = u.i & 0xFFFFFFFFFFFFFULL;
return (exp == 0x7FF) && (mantissa == 0);
}
+14
View File
@@ -0,0 +1,14 @@
#include <math.h>
#include <stdint.h>
int isnan(double x) {
union {
double f;
uint64_t i;
} u = { .f = x };
uint64_t exp = (u.i >> 52) & 0x7FF;
uint64_t mantissa = u.i & 0xFFFFFFFFFFFFFULL;
return (exp == 0x7FF) && (mantissa != 0);
}
+37
View File
@@ -0,0 +1,37 @@
#include <math.h>
double pow(double x, double y) {
if (y == 0.0) return 1.0;
if (y == (int)y) {
int n = (int)y;
double result = 1.0;
if (n > 0) {
for (int i = 0; i < n; i++) {
result *= x;
}
} else {
for (int i = 0; i < -n; i++) {
result /= x;
}
}
return result;
}
if (x > 0.0) {
int int_part = (int)y;
double frac_part = y - int_part;
double int_pow = pow(x, int_part);
if (frac_part > 0.0) {
return int_pow * (1.0 + frac_part * (x - 1.0));
} else {
return int_pow / (1.0 - frac_part * (x - 1.0));
}
}
return NAN;
}
+17
View File
@@ -0,0 +1,17 @@
#include <math.h>
double pow10(int n) {
double result = 1.0;
if (n >= 0) {
for (int i = 0; i < n; i++) {
result *= 10.0;
}
} else {
for (int i = 0; i < -n; i++) {
result /= 10.0;
}
}
return result;
}
+6
View File
@@ -0,0 +1,6 @@
#include <stdio.h>
#include "../../../kernel/include/drivers/ps2.h"
int getchar(void) {
return (unsigned char)kb_buf_getc();
}
+9
View File
@@ -0,0 +1,9 @@
#include <stdio.h>
#include <stdarg.h>
int printf(const char *format, ...) {
va_list args;
va_start(args, format);
int n = vprintf(format, args);
return n;
}
+360
View File
@@ -0,0 +1,360 @@
#include <stdio.h>
#include <string.h>
#include "../../../kernel/include/graphics/fb/fb.h"
uint32_t cursor_x = 0;
uint32_t cursor_y = 0;
uint32_t text_color = COLOR_WHITE;
uint32_t bg_color = COLOR_BLACK;
extern struct limine_framebuffer *global_framebuffer;
static int cursor_visible = 1;
static int scroll_buffer_index = 0;
static int total_scroll_lines = 0;
static int flush_inhibit = 0;
static int autowrap = 1;
uint32_t get_screen_width(void) {
if (!global_framebuffer) return 1024;
return global_framebuffer->width;
}
uint32_t get_screen_height(void) {
if (!global_framebuffer) return 768;
return global_framebuffer->height;
}
uint32_t get_cursor_row(void) { return cursor_y / 16; }
uint32_t get_cursor_col(void) { return cursor_x / 8; }
static void flush_all(void) {
if (!flush_inhibit && global_framebuffer)
fb_flush(global_framebuffer);
}
static void flush_region(uint32_t y_start, uint32_t h) {
if (!flush_inhibit && global_framebuffer)
fb_flush_lines(global_framebuffer, y_start, y_start + h);
}
void scroll_screen(int lines) {
if (!global_framebuffer || lines <= 0) return;
uint32_t sh = get_screen_height();
uint32_t sp = (uint32_t)(lines * 16);
if (sp >= sh) { fb_clear(global_framebuffer, bg_color); flush_all(); return; }
uint32_t *buf = (uint32_t *)global_framebuffer->address;
extern uint32_t *g_backbuf;
extern uint32_t g_bb_pitch;
uint32_t pitch;
uint32_t *target;
if (g_backbuf) {
target = g_backbuf;
pitch = g_bb_pitch;
} else {
target = buf;
pitch = global_framebuffer->pitch / 4;
}
uint32_t rows_to_move = sh - sp;
memmove(target, target + sp * pitch, rows_to_move * pitch * sizeof(uint32_t));
memset(target + rows_to_move * pitch, 0, sp * pitch * sizeof(uint32_t));
if (bg_color != 0) {
uint32_t sw = get_screen_width();
uint32_t *clear_start = target + rows_to_move * pitch;
for (uint32_t y = 0; y < sp; y++) {
uint32_t *row = clear_start + y * pitch;
for (uint32_t x = 0; x < sw; x++)
row[x] = bg_color;
}
}
flush_all();
}
static void draw_cursor_at(uint32_t x, uint32_t y) {
if (!global_framebuffer || !cursor_visible) return;
if (x + 8 > global_framebuffer->width || y + 16 > global_framebuffer->height) return;
for (uint32_t col = 0; col < 8; col++) {
fb_draw_pixel(global_framebuffer, x + col, y + 14, text_color);
fb_draw_pixel(global_framebuffer, x + col, y + 15, text_color);
}
flush_region(y + 14, 2);
}
static void erase_cursor_at(uint32_t x, uint32_t y) {
if (!global_framebuffer) return;
if (x + 8 > global_framebuffer->width || y + 16 > global_framebuffer->height) return;
for (uint32_t col = 0; col < 8; col++) {
fb_draw_pixel(global_framebuffer, x + col, y + 14, bg_color);
fb_draw_pixel(global_framebuffer, x + col, y + 15, bg_color);
}
flush_region(y + 14, 2);
}
void draw_cursor(void) { draw_cursor_at(cursor_x, cursor_y); }
void erase_cursor(void) { erase_cursor_at(cursor_x, cursor_y); }
static uint32_t ansi_color(int code, int bright) {
static const uint32_t base[8] = {
0x000000, 0xAA0000, 0x00AA00, 0xAA5500,
0x0000AA, 0xAA00AA, 0x00AAAA, 0xAAAAAA,
};
static const uint32_t bright8[8] = {
0x555555, 0xFF5555, 0x55FF55, 0xFFFF55,
0x5555FF, 0xFF55FF, 0x55FFFF, 0xFFFFFF,
};
return bright ? bright8[code & 7] : base[code & 7];
}
#define ESC_MAX_PARAMS 8
typedef enum {
PS_NORMAL,
PS_ESC,
PS_CSI,
PS_CSI_PRIV,
PS_ESC_SP,
} parse_state_t;
static parse_state_t ps_state = PS_NORMAL;
static int ps_params[ESC_MAX_PARAMS];
static int ps_nparams = 0;
static int ps_cur = 0;
static int ps_bold = 0;
static void ps_reset_params(void) {
for (int i = 0; i < ESC_MAX_PARAMS; i++) ps_params[i] = -1;
ps_nparams = 0; ps_cur = 0;
}
static void ps_push_param(void) {
if (ps_nparams < ESC_MAX_PARAMS) ps_params[ps_nparams++] = ps_cur;
ps_cur = 0;
}
static int ps_get(int i, int def) {
if (i >= ps_nparams || ps_params[i] < 0) return def;
return ps_params[i];
}
static int ps_reverse = 0;
static void handle_sgr(void) {
if (ps_nparams == 0) {
text_color = COLOR_WHITE; bg_color = COLOR_BLACK;
ps_bold = 0; ps_reverse = 0;
return;
}
for (int i = 0; i < ps_nparams; i++) {
int p = ps_params[i]; if (p < 0) p = 0;
if (p == 0) { text_color = COLOR_WHITE; bg_color = COLOR_BLACK; ps_bold = 0; ps_reverse = 0; }
else if (p == 1) { ps_bold = 1; }
else if (p == 22) { ps_bold = 0; }
else if (p == 7) {
if (!ps_reverse) {
uint32_t tmp = text_color; text_color = bg_color; bg_color = tmp;
ps_reverse = 1;
}
}
else if (p == 27) {
if (ps_reverse) {
uint32_t tmp = text_color; text_color = bg_color; bg_color = tmp;
ps_reverse = 0;
}
}
else if (p >= 30 && p <= 37) {
uint32_t c = ansi_color(p-30, ps_bold);
if (ps_reverse) bg_color = c; else text_color = c;
}
else if (p >= 90 && p <= 97) {
uint32_t c = ansi_color(p-90, 1);
if (ps_reverse) bg_color = c; else text_color = c;
}
else if (p >= 40 && p <= 47) {
uint32_t c = ansi_color(p-40, 0);
if (ps_reverse) text_color = c; else bg_color = c;
}
}
}
static void erase_to_eol(void) {
if (!global_framebuffer) return;
uint32_t sw = get_screen_width();
if (cursor_x >= sw) return;
fb_fill_rect(global_framebuffer, cursor_x, cursor_y, sw - cursor_x, 16, bg_color);
flush_region(cursor_y, 16);
}
static void cursor_move_right(int n) {
uint32_t sw = get_screen_width();
cursor_x += (uint32_t)(n * 8);
if (cursor_x + 8 > sw) cursor_x = sw - 8;
}
static void cursor_move_left(int n) {
uint32_t delta = (uint32_t)(n * 8);
if (cursor_x >= delta) cursor_x -= delta;
else cursor_x = 0;
}
static uint32_t saved_cx = 0, saved_cy = 0;
static void clear_cell(uint32_t x, uint32_t y) {
if (!global_framebuffer) return;
fb_fill_rect(global_framebuffer, x, y, 8, 16, bg_color);
}
static void draw_and_advance(char c) {
if (!global_framebuffer) return;
uint32_t sh = get_screen_height();
uint32_t sw = get_screen_width();
if (!autowrap && cursor_x + 8 >= sw) {
clear_cell(cursor_x, cursor_y);
fb_draw_char(global_framebuffer, c, cursor_x, cursor_y, text_color);
flush_region(cursor_y, 16);
return;
}
clear_cell(cursor_x, cursor_y);
fb_draw_char(global_framebuffer, c, cursor_x, cursor_y, text_color);
flush_region(cursor_y, 16);
cursor_x += 8;
if (cursor_x + 8 > sw) { cursor_x = 0; cursor_y += 16; }
if (cursor_y + 16 > sh) { scroll_screen(1); cursor_y = sh - 16; }
}
int putchar(int c) {
if (!global_framebuffer) return EOF;
uint8_t ch = (uint8_t)c;
switch (ps_state) {
case PS_NORMAL:
if (ch == 0x1B) { ps_state = PS_ESC; return c; }
switch (ch) {
case '\n':
cursor_x = 0; cursor_y += 16;
if (cursor_y + 16 > get_screen_height()) {
scroll_screen(1); cursor_y = get_screen_height() - 16;
}
break;
case '\r': cursor_x = 0; break;
case '\t': cursor_x = (cursor_x + 32) & ~31u; break;
case '\b':
if (cursor_x >= 8) {
cursor_x -= 8;
clear_cell(cursor_x, cursor_y);
flush_region(cursor_y, 16);
}
break;
default:
if (ch >= 32 && ch <= 126) draw_and_advance((char)ch);
break;
}
break;
case PS_ESC:
if (ch == '[') { ps_state = PS_CSI; ps_reset_params(); }
else if (ch == ' ') { ps_state = PS_ESC_SP; }
else { ps_state = PS_NORMAL; }
break;
case PS_ESC_SP:
ps_state = PS_NORMAL;
break;
case PS_CSI:
if (ch == '?') { ps_state = PS_CSI_PRIV; break; }
__attribute__((fallthrough));
case PS_CSI_PRIV:
if (ch >= '0' && ch <= '9') {
ps_cur = ps_cur * 10 + (ch - '0');
} else if (ch == ';') {
ps_push_param();
} else {
ps_push_param();
if (ps_state == PS_CSI_PRIV) {
int p = ps_get(0, 0);
if (p == 25) {
if (ch == 'l') {
cursor_visible = 0;
flush_inhibit = 1;
} else if (ch == 'h') {
cursor_visible = 1;
flush_inhibit = 0;
if (global_framebuffer)
fb_flush(global_framebuffer);
}
} else if (p == 7) {
if (ch == 'l') autowrap = 0;
else if (ch == 'h') autowrap = 1;
}
ps_state = PS_NORMAL;
break;
}
switch (ch) {
case 'm': handle_sgr(); break;
case 'J': {
int mode = ps_get(0, 0);
if (mode == 2 || mode == 3) {
fb_clear(global_framebuffer, bg_color);
cursor_x = 0; cursor_y = 0;
flush_all();
}
break;
}
case 'K': {
int mode = ps_get(0, 0);
if (mode == 0) erase_to_eol();
break;
}
case 'H':
case 'f': {
int row = ps_get(0, 1); if (row < 1) row = 1;
int col = ps_get(1, 1); if (col < 1) col = 1;
uint32_t cx = (uint32_t)((col - 1) * 8);
uint32_t cy = (uint32_t)((row - 1) * 16);
uint32_t sw = get_screen_width();
uint32_t sh = get_screen_height();
if (cx + 8 > sw) cx = (sw >= 8) ? sw - 8 : 0;
if (cy + 16 > sh) cy = (sh >= 16) ? sh - 16 : 0;
cursor_x = cx;
cursor_y = cy;
break;
}
case 'A': {
int n = ps_get(0, 1); if (n < 1) n = 1;
uint32_t d = (uint32_t)(n * 16);
cursor_y = (cursor_y >= d) ? cursor_y - d : 0;
break;
}
case 'B': {
int n = ps_get(0, 1); if (n < 1) n = 1;
cursor_y += (uint32_t)(n * 16);
break;
}
case 'C': cursor_move_right(ps_get(0, 1)); break;
case 'D': cursor_move_left (ps_get(0, 1)); break;
case 's': saved_cx = cursor_x; saved_cy = cursor_y; break;
case 'u': cursor_x = saved_cx; cursor_y = saved_cy; break;
default: break;
}
ps_state = PS_NORMAL;
}
break;
}
return c;
}
void clear_screen_with_scroll(void) {
if (global_framebuffer) {
fb_clear(global_framebuffer, bg_color);
cursor_x = 0; cursor_y = 0;
scroll_buffer_index = 0; total_scroll_lines = 0;
flush_all();
}
}
void get_cursor_position(uint32_t *x, uint32_t *y) {
if (x) *x = cursor_x;
if (y) *y = cursor_y;
}
+27
View File
@@ -0,0 +1,27 @@
#include <stdio.h>
#include <string.h>
int puts(const char *str) {
int count = 0;
if (!str) {
const char *null_str = "(null)";
while (*null_str) {
putchar(*null_str++);
count++;
}
putchar('\n');
count++;
return count;
}
while (*str) {
putchar(*str++);
count++;
}
putchar('\n');
count++;
return count;
}
+246
View File
@@ -0,0 +1,246 @@
#include <stdio.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdlib.h>
#include "../../kernel/include/drivers/ps2.h"
#include "../../kernel/include/graphics/fb/fb.h"
extern struct limine_framebuffer *global_framebuffer;
extern uint32_t bg_color;
static int readline_buf(char *buf, size_t size) {
if (!buf || size == 0) return 0;
uint32_t prompt_x, prompt_y;
get_cursor_position(&prompt_x, &prompt_y);
size_t len = 0;
while (len < size - 1) {
int c = getchar();
if (c == EOF) break;
if (c == '\n' || c == '\r') {
putchar('\n');
break;
}
if (c == '\b') {
if (len == 0) continue;
len--;
if (cursor_x >= 8) {
cursor_x -= 8;
} else if (cursor_y > prompt_y ||
(cursor_y == prompt_y && cursor_x > prompt_x)) {
cursor_y -= 16;
cursor_x = (get_screen_width() / 8) * 8 - 8;
} else {
continue;
}
if (global_framebuffer)
fb_fill_rect(global_framebuffer,
cursor_x, cursor_y, 8, 16, bg_color);
continue;
}
if ((unsigned char)c < 32 && c != '\t') continue;
buf[len++] = (char)c;
putchar(c);
}
buf[len] = '\0';
return (int)len;
}
int vsscanf(const char *str, const char *fmt, va_list ap) {
if (!str || !fmt) return EOF;
const char *s = str;
const char *f = fmt;
int n = 0;
while (*f) {
if (*f == ' ' || *f == '\t' || *f == '\n' || *f == '\r') {
while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r')
s++;
f++;
continue;
}
if (*f != '%') {
if (*s != *f) break;
s++; f++;
continue;
}
f++;
bool suppress = false;
if (*f == '*') { suppress = true; f++; }
int width = 0;
while (*f >= '0' && *f <= '9') {
width = width * 10 + (*f - '0');
f++;
}
enum { LEN_INT, LEN_LONG, LEN_LLONG } len = LEN_INT;
if (*f == 'l') {
f++;
if (*f == 'l') { f++; len = LEN_LLONG; }
else { len = LEN_LONG; }
} else if (*f == 'h') {
f++;
if (*f == 'h') f++;
}
char spec = *f++;
if (spec == '%') {
while (*s == ' ' || *s == '\t') s++;
if (*s != '%') break;
s++;
continue;
}
if (spec == 'n') {
if (!suppress) {
*va_arg(ap, int *) = (int)(s - str);
}
continue;
}
if (spec == 'c') {
if (!*s) break;
if (!suppress) {
char *out = va_arg(ap, char *);
*out = *s;
n++;
}
s++;
continue;
}
while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r')
s++;
if (!*s) break;
if (spec == 's') {
char *out = suppress ? NULL : va_arg(ap, char *);
int cnt = 0;
while (*s && *s != ' ' && *s != '\t' &&
*s != '\n' && *s != '\r') {
if (width && cnt >= width) break;
if (out) out[cnt] = *s;
cnt++;
s++;
}
if (cnt == 0) break;
if (out) { out[cnt] = '\0'; n++; }
continue;
}
int base = 10;
bool is_signed = false;
switch (spec) {
case 'd': base = 10; is_signed = true; break;
case 'i': base = 0; is_signed = true; break;
case 'u': base = 10; is_signed = false; break;
case 'o': base = 8; is_signed = false; break;
case 'x':
case 'X': base = 16; is_signed = false; break;
default:
goto done;
}
char tmp[32];
int tlen = 0;
int maxw = width ? width : (int)sizeof(tmp) - 1;
if (is_signed && (*s == '-' || *s == '+') && tlen < maxw)
tmp[tlen++] = *s++;
if ((base == 16 || base == 0) &&
*s == '0' && (s[1] == 'x' || s[1] == 'X') && tlen + 2 <= maxw) {
tmp[tlen++] = *s++; tmp[tlen++] = *s++;
if (base == 0) base = 16;
} else if (base == 0 && *s == '0') {
tmp[tlen++] = *s++;
base = 8;
} else if (base == 0) {
base = 10;
}
while (*s && tlen < maxw) {
char c = *s;
bool ok = false;
if (base == 10 && c >= '0' && c <= '9') ok = true;
if (base == 8 && c >= '0' && c <= '7') ok = true;
if (base == 16 && ((c >= '0' && c <= '9') ||
(c >= 'a' && c <= 'f') ||
(c >= 'A' && c <= 'F'))) ok = true;
if (!ok) break;
tmp[tlen++] = c;
s++;
}
if (tlen == 0) break;
tmp[tlen] = '\0';
if (!suppress) {
char *end = NULL;
if (is_signed) {
long long val = strtoll(tmp, &end, base);
if (end == tmp) break;
switch (len) {
case LEN_INT: *va_arg(ap, int *) = (int)val; break;
case LEN_LONG: *va_arg(ap, long *) = (long)val; break;
case LEN_LLONG: *va_arg(ap, long long *) = val; break;
}
} else {
unsigned long long val = strtoull(tmp, &end, base);
if (end == tmp) break;
switch (len) {
case LEN_INT: *va_arg(ap, unsigned int *) = (unsigned int)val; break;
case LEN_LONG: *va_arg(ap, unsigned long *) = (unsigned long)val; break;
case LEN_LLONG: *va_arg(ap, unsigned long long *) = val; break;
}
}
n++;
}
}
done:
return n;
}
int sscanf(const char * restrict str, const char * restrict fmt, ...) {
va_list ap;
va_start(ap, fmt);
int r = vsscanf(str, fmt, ap);
va_end(ap);
return r;
}
int vscanf(const char * restrict fmt, va_list ap) {
char buf[256];
readline_buf(buf, sizeof(buf));
return vsscanf(buf, fmt, ap);
}
int scanf(const char * restrict fmt, ...) {
va_list ap;
va_start(ap, fmt);
int r = vscanf(fmt, ap);
va_end(ap);
return r;
}
+38
View File
@@ -0,0 +1,38 @@
#include <stdio.h>
#include "../../../kernel/include/graphics/fb/fb.h"
extern struct limine_framebuffer *global_framebuffer;
void set_cursor_position(uint32_t x, uint32_t y) {
cursor_x = x;
cursor_y = y;
}
void set_text_color(uint32_t color) {
text_color = color;
}
void set_background_color(uint32_t color) {
bg_color = color;
}
void clear_screen(void) {
if (global_framebuffer) {
fb_clear(global_framebuffer, bg_color);
cursor_x = 0;
cursor_y = 0;
}
}
void scroll_up(int lines) {
if (lines <= 0) return;
scroll_screen(lines);
uint32_t scroll_pixels = (uint32_t)(lines * 16);
if (cursor_y >= scroll_pixels) {
cursor_y -= scroll_pixels;
} else {
cursor_y = 0;
}
}
+381
View File
@@ -0,0 +1,381 @@
#include <stdio.h>
#include <stdarg.h>
#include <stddef.h>
#include <string.h>
typedef struct {
char* buf;
size_t pos;
size_t size;
} snprintf_ctx_t;
static void ctx_putc(snprintf_ctx_t* ctx, char c) {
if (ctx->pos + 1 < ctx->size)
ctx->buf[ctx->pos] = c;
ctx->pos++;
}
static void ctx_puts(snprintf_ctx_t* ctx, const char* s, int len) {
for (int i = 0; i < len; i++) ctx_putc(ctx, s[i]);
}
static void write_uint_full(snprintf_ctx_t* ctx,
unsigned long long val, int base, int upper,
int width, int zero_pad, int left,
int alt, int show_sign, int space_sign,
char forced_sign) {
const char* digs = upper ? "0123456789ABCDEF" : "0123456789abcdef";
char tmp[72]; int len = 0;
if (val == 0) { tmp[len++] = '0'; }
else { while (val) { tmp[len++] = digs[val % (unsigned)base]; val /= (unsigned)base; } }
char prefix[4]; int pfx = 0;
if (forced_sign) prefix[pfx++] = forced_sign;
else if (show_sign) prefix[pfx++] = '+';
else if (space_sign) prefix[pfx++] = ' ';
if (alt && base == 16) { prefix[pfx++] = '0'; prefix[pfx++] = upper ? 'X':'x'; }
else if (alt && base == 8 && !(len==1 && tmp[0]=='0')) { prefix[pfx++] = '0'; }
else if (alt && base == 2) { prefix[pfx++] = '0'; prefix[pfx++] = upper ? 'B':'b'; }
int total = len + pfx;
int pad = (width > total) ? width - total : 0;
if (!left && !zero_pad) { for (int i=0;i<pad;i++) ctx_putc(ctx,' '); }
ctx_puts(ctx, prefix, pfx);
if (!left && zero_pad) { for (int i=0;i<pad;i++) ctx_putc(ctx,'0'); }
for (int i = len-1; i >= 0; i--) ctx_putc(ctx, tmp[i]);
if ( left) { for (int i=0;i<pad;i++) ctx_putc(ctx,' '); }
}
static void write_sint(snprintf_ctx_t* ctx, long long val,
int width, int zero_pad, int left,
int show_sign, int space_sign) {
char sign = 0;
unsigned long long uval;
if (val < 0) { sign = '-'; uval = (unsigned long long)(-val); }
else { uval = (unsigned long long)val; }
write_uint_full(ctx, uval, 10, 0, width, zero_pad, left,
0, show_sign, space_sign, sign);
}
static const unsigned long long pow10_tbl[18] = {
1ULL, 10ULL, 100ULL, 1000ULL, 10000ULL, 100000ULL,
1000000ULL, 10000000ULL, 100000000ULL, 1000000000ULL,
10000000000ULL, 100000000000ULL, 1000000000000ULL,
10000000000000ULL, 100000000000000ULL, 1000000000000000ULL,
10000000000000000ULL, 100000000000000000ULL
};
static int ilog10(double val) {
int e = 0;
if (val >= 1.0) {
if (val >= 1e16) { val /= 1e16; e += 16; }
if (val >= 1e8) { val /= 1e8; e += 8; }
if (val >= 1e4) { val /= 1e4; e += 4; }
if (val >= 1e2) { val /= 1e2; e += 2; }
if (val >= 1e1) { val /= 1e1; e += 1; }
} else {
if (val < 1e-15) { val *= 1e16; e -= 16; }
if (val < 1e-7) { val *= 1e8; e -= 8; }
if (val < 1e-3) { val *= 1e4; e -= 4; }
if (val < 1e-1) { val *= 1e2; e -= 2; }
if (val < 1e0) { val *= 1e1; e -= 1; }
}
(void)val;
return e;
}
static int double_to_str(char* buf, double val, char fmt_char, int precision,
int show_sign, int space_sign, int alt, int is_neg) {
if (precision < 0) precision = 6;
if (precision > 17) precision = 17;
int upper = (fmt_char == 'F' || fmt_char == 'E' || fmt_char == 'G');
int i = 0;
if (is_neg) buf[i++] = '-';
else if (show_sign) buf[i++] = '+';
else if (space_sign) buf[i++] = ' ';
int exp10 = (val != 0.0) ? ilog10(val) : 0;
int use_exp;
if (fmt_char == 'e' || fmt_char == 'E') {
use_exp = 1;
} else if (fmt_char == 'g' || fmt_char == 'G') {
int eff = (precision == 0) ? 1 : precision;
use_exp = (exp10 < -4 || exp10 >= eff);
precision = use_exp ? (eff - 1) : (eff - 1 - exp10);
if (precision < 0) precision = 0;
if (precision > 17) precision = 17;
} else {
use_exp = (exp10 > 15 || (val != 0.0 && exp10 < -17));
if (use_exp) { fmt_char = upper ? 'E' : 'e'; upper = (fmt_char == 'E'); }
}
double src = val;
if (use_exp && val != 0.0) {
int e = exp10;
if (e > 0 && e <= 17) src /= (double)pow10_tbl[e];
else if (e > 17) { src /= (double)pow10_tbl[17]; src /= (double)pow10_tbl[e - 17 < 17 ? e-17 : 17]; }
else if (e < 0 && -e <= 17) src *= (double)pow10_tbl[-e];
else if (e < -17) { src *= (double)pow10_tbl[17]; src *= (double)pow10_tbl[-e-17 < 17 ? -e-17 : 17]; }
if (src >= 10.0) { src /= 10.0; exp10++; }
if (src < 1.0 && src != 0.0) { src *= 10.0; exp10--; }
}
unsigned long long scale = pow10_tbl[precision];
double scaled_d = src * (double)scale + 0.5;
if (scaled_d >= 1.8e19) scaled_d = 1.8e19 - 1.0;
unsigned long long iscaled = (unsigned long long)scaled_d;
unsigned long long int_part = iscaled / scale;
unsigned long long frac_part = iscaled % scale;
if (use_exp && int_part >= 10) { int_part = 1; frac_part = 0; exp10++; }
{
char itmp[24]; int ilen = 0;
unsigned long long ip = int_part;
if (ip == 0) itmp[ilen++] = '0';
else while (ip) { itmp[ilen++] = '0' + (int)(ip % 10); ip /= 10; }
for (int j = ilen-1; j >= 0; j--) buf[i++] = itmp[j];
}
if (precision > 0 || alt) {
char ftmp[20];
unsigned long long fp2 = frac_part;
for (int k = precision - 1; k >= 0; k--) {
ftmp[k] = '0' + (int)(fp2 % 10);
fp2 /= 10;
}
int fend = precision;
if ((fmt_char == 'g' || fmt_char == 'G') && !alt) {
while (fend > 0 && ftmp[fend-1] == '0') fend--;
}
if (fend > 0 || alt) {
buf[i++] = '.';
for (int k = 0; k < fend; k++) buf[i++] = ftmp[k];
}
}
if (use_exp) {
buf[i++] = upper ? 'E' : 'e';
int ae = exp10 < 0 ? -exp10 : exp10;
buf[i++] = exp10 < 0 ? '-' : '+';
if (ae >= 100) buf[i++] = '0' + ae / 100;
buf[i++] = '0' + (ae / 10) % 10;
buf[i++] = '0' + ae % 10;
}
return i;
}
static void write_float(snprintf_ctx_t* ctx, double val, char fmt_char,
int precision, int width, int zero_pad, int left,
int show_sign, int space_sign, int alt) {
char tmp[64]; int len;
int upper = (fmt_char == 'F' || fmt_char == 'E' || fmt_char == 'G');
if (val != val) {
const char* s = upper ? "NAN" : "nan";
len = 3; tmp[0]=s[0]; tmp[1]=s[1]; tmp[2]=s[2];
} else {
int is_neg = 0;
if (val < 0.0) { is_neg = 1; val = -val; }
if (val > 1.7976931348623157e+308) {
len = 0;
if (is_neg) tmp[len++] = '-';
else if (show_sign) tmp[len++] = '+';
else if (space_sign) tmp[len++] = ' ';
const char* s = upper ? "INF" : "inf";
tmp[len++]=s[0]; tmp[len++]=s[1]; tmp[len++]=s[2];
} else {
len = double_to_str(tmp, val, fmt_char, precision,
show_sign, space_sign, alt, is_neg);
}
}
int has_sign = (tmp[0]=='-' || tmp[0]=='+' || tmp[0]==' ');
int pad = (width > len) ? width - len : 0;
if (!left && !zero_pad) { for (int j=0;j<pad;j++) ctx_putc(ctx,' '); }
if (!left && zero_pad) {
if (has_sign) ctx_putc(ctx, tmp[0]);
for (int j=0;j<pad;j++) ctx_putc(ctx,'0');
ctx_puts(ctx, tmp + has_sign, len - has_sign);
} else {
ctx_puts(ctx, tmp, len);
}
if (left) { for (int j=0;j<pad;j++) ctx_putc(ctx,' '); }
}
int vsnprintf(char* restrict buf, size_t size, const char* restrict fmt,
va_list ap) {
snprintf_ctx_t ctx = { buf, 0, size ? size : 1 };
for (; *fmt; fmt++) {
if (*fmt != '%') { ctx_putc(&ctx, *fmt); continue; }
fmt++;
if (!*fmt) break;
int left=0, zero_pad=0, alt=0, show_sign=0, space_sign=0;
for (;;) {
if (*fmt=='-') { left=1; fmt++; }
else if (*fmt=='0') { zero_pad=1; fmt++; }
else if (*fmt=='#') { alt=1; fmt++; }
else if (*fmt=='+') { show_sign=1; fmt++; }
else if (*fmt==' ') { space_sign=1; fmt++; }
else break;
}
int width = 0;
if (*fmt == '*') {
width = va_arg(ap, int);
if (width < 0) { left = 1; width = -width; }
fmt++;
} else {
while (*fmt >= '0' && *fmt <= '9') width = width*10 + (*fmt++ - '0');
}
int precision=-1, has_prec=0;
if (*fmt == '.') {
has_prec=1; precision=0; fmt++;
if (*fmt == '*') {
precision = va_arg(ap, int);
if (precision < 0) { has_prec=0; precision=-1; }
fmt++;
} else {
while (*fmt >= '0' && *fmt <= '9')
precision = precision*10 + (*fmt++ - '0');
}
}
int is_hh=0,is_h=0,is_l=0,is_ll=0,is_z=0;
if (*fmt=='h') {
fmt++;
if (*fmt=='h') { is_hh=1; fmt++; } else is_h=1;
} else if (*fmt=='l') {
is_l=1; fmt++;
if (*fmt=='l') { is_ll=1; fmt++; }
} else if (*fmt=='z') { is_z=1; fmt++; }
else if (*fmt=='t') { is_l=1; fmt++; }
else if (*fmt=='L') { fmt++; }
if (!*fmt) break;
switch (*fmt) {
case 'd': case 'i': {
long long v;
if (is_ll) v = va_arg(ap, long long);
else if (is_l) v = va_arg(ap, long);
else if (is_hh) v = (signed char) va_arg(ap, int);
else if (is_h) v = (short) va_arg(ap, int);
else if (is_z) v = (long long) va_arg(ap, size_t);
else v = va_arg(ap, int);
write_sint(&ctx, v, width, zero_pad, left, show_sign, space_sign);
break;
}
case 'u': {
unsigned long long v;
if (is_ll) v = va_arg(ap, unsigned long long);
else if (is_l) v = va_arg(ap, unsigned long);
else if (is_hh) v = (unsigned char) va_arg(ap, unsigned int);
else if (is_h) v = (unsigned short)va_arg(ap, unsigned int);
else if (is_z) v = va_arg(ap, size_t);
else v = va_arg(ap, unsigned int);
write_uint_full(&ctx,v,10,0,width,zero_pad,left,0,show_sign,space_sign,0);
break;
}
case 'o': {
unsigned long long v;
if (is_ll) v = va_arg(ap, unsigned long long);
else if (is_l) v = va_arg(ap, unsigned long);
else v = va_arg(ap, unsigned int);
write_uint_full(&ctx,v,8,0,width,zero_pad,left,alt,0,0,0);
break;
}
case 'x': case 'X': {
unsigned long long v;
if (is_ll) v = va_arg(ap, unsigned long long);
else if (is_l) v = va_arg(ap, unsigned long);
else v = va_arg(ap, unsigned int);
write_uint_full(&ctx,v,16,(*fmt=='X'),width,zero_pad,left,alt,0,0,0);
break;
}
case 'b': case 'B': {
unsigned long long v;
if (is_ll) v = va_arg(ap, unsigned long long);
else if (is_l) v = va_arg(ap, unsigned long);
else v = va_arg(ap, unsigned int);
write_uint_full(&ctx,v,2,(*fmt=='B'),width,zero_pad,left,alt,0,0,0);
break;
}
case 'p': {
uintptr_t v = (uintptr_t)va_arg(ap, void*);
ctx_putc(&ctx,'0'); ctx_putc(&ctx,'x');
write_uint_full(&ctx,(unsigned long long)v,16,0,width,1,left,0,0,0,0);
break;
}
case 'f': case 'F':
case 'e': case 'E':
case 'g': case 'G': {
double v = va_arg(ap, double);
write_float(&ctx, v, *fmt,
has_prec ? precision : 6,
width, zero_pad, left, show_sign, space_sign, alt);
break;
}
case 's': {
const char* s = va_arg(ap, const char*);
if (!s) s = "(null)";
int slen = (int)strlen(s);
if (has_prec && precision < slen) slen = precision;
int pad = (width > slen) ? width - slen : 0;
if (!left) { for (int j=0;j<pad;j++) ctx_putc(&ctx,' '); }
ctx_puts(&ctx, s, slen);
if ( left) { for (int j=0;j<pad;j++) ctx_putc(&ctx,' '); }
break;
}
case 'c': {
char c = (char)va_arg(ap, int);
int pad = (width > 1) ? width - 1 : 0;
if (!left) { for (int j=0;j<pad;j++) ctx_putc(&ctx,' '); }
ctx_putc(&ctx, c);
if ( left) { for (int j=0;j<pad;j++) ctx_putc(&ctx,' '); }
break;
}
case 'n': {
int* p = va_arg(ap, int*);
if (p) *p = (int)ctx.pos;
break;
}
case '%': ctx_putc(&ctx,'%'); break;
default: ctx_putc(&ctx,'%'); ctx_putc(&ctx,*fmt); break;
}
}
if (size > 0) buf[ctx.pos < size ? ctx.pos : size-1] = '\0';
return (int)ctx.pos;
}
int vprintf(const char* restrict fmt, va_list ap) {
char buf[1024];
int n = vsnprintf(buf, sizeof(buf), fmt, ap);
for (int i = 0; i < n && buf[i]; i++) putchar(buf[i]);
return n;
}
int vsprintf(char* restrict buf, const char* restrict fmt, va_list ap) {
return vsnprintf(buf, (size_t)-1, fmt, ap);
}
int snprintf(char* restrict buf, size_t size, const char* restrict fmt, ...) {
va_list ap; va_start(ap, fmt);
int n = vsnprintf(buf, size, fmt, ap);
va_end(ap); return n;
}
int sprintf(char* restrict buf, const char* restrict fmt, ...) {
va_list ap; va_start(ap, fmt);
int n = vsnprintf(buf, (size_t)-1, fmt, ap);
va_end(ap); return n;
}
+14
View File
@@ -0,0 +1,14 @@
#include <stdlib.h>
#include "../../../kernel/include/memory/pmm.h"
void *aligned_alloc(size_t alignment, size_t size) {
if (size == 0) return NULL;
if (alignment == 0 || (alignment & (alignment - 1))) return NULL;
if (alignment < 16) alignment = 16;
void *raw = kmalloc(size + alignment + sizeof(void *));
if (!raw) return NULL;
uintptr_t addr = (uintptr_t)raw + sizeof(void *);
uintptr_t aligned = (addr + alignment - 1) & ~(alignment - 1);
((void **)aligned)[-1] = raw;
return (void *)aligned;
}
+8
View File
@@ -0,0 +1,8 @@
#include <stdlib.h>
#include "../../../kernel/include/memory/pmm.h"
void aligned_free(void* ptr) {
if (!ptr) return;
void* raw = ((void**)ptr)[-1];
kfree(raw);
}
+11
View File
@@ -0,0 +1,11 @@
#include <stdlib.h>
#include <string.h>
#include "../../../kernel/include/memory/pmm.h"
void *calloc(size_t nmemb, size_t size) {
if (nmemb == 0 || size == 0) return NULL;
if (nmemb > (size_t)-1 / size) return NULL;
void *ptr = kmalloc(nmemb * size);
if (ptr) memset(ptr, 0, nmemb * size);
return ptr;
}
+6
View File
@@ -0,0 +1,6 @@
#include <stdlib.h>
#include "../../../kernel/include/memory/pmm.h"
void free(void *ptr) {
kfree(ptr);
}
+41
View File
@@ -0,0 +1,41 @@
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
char *itoa(int val, char *restrict str, int base) {
int i = 0;
bool negative = false;
if (val == 0) {
str[i++] = '0';
str[i] = '\0';
return str;
}
if (val < 0 && base == 10) {
negative = true;
val = -val;
}
while (val != 0) {
int rem = val % base;
str[i++] = (rem > 9) ? (rem - 10) + 'a' : rem + '0';
val = val / base;
}
if (negative)
str[i++] = '-';
str[i] = '\0';
int start = 0, end = strlen(str) - 1;
while (start < end) {
char temp = str[start];
str[start] = str[end];
str[end] = temp;
end--;
start++;
}
return str;
}
+7
View File
@@ -0,0 +1,7 @@
#include <stdlib.h>
#include "../../../kernel/include/memory/pmm.h"
void *malloc(size_t size) {
if (size == 0) return NULL;
return kmalloc(size);
}
+7
View File
@@ -0,0 +1,7 @@
#include <stdlib.h>
#include <string.h>
#include "../../../kernel/include/memory/pmm.h"
void *realloc(void *ptr, size_t size) {
return krealloc(ptr, size);
}
+40
View File
@@ -0,0 +1,40 @@
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
long long strtoll(const char * restrict s, char ** restrict end, int base) {
while (*s == ' ' || *s == '\t') s++;
bool neg = false;
if (*s == '-') { neg = true; s++; }
else if (*s == '+') { s++; }
if (base == 0) {
if (*s == '0' && (s[1] == 'x' || s[1] == 'X')) { base = 16; s += 2; }
else if (*s == '0') { base = 8; s++; }
else { base = 10; }
} else if (base == 16 && *s == '0' && (s[1] == 'x' || s[1] == 'X')) {
s += 2;
}
unsigned long long acc = 0;
const char *start = s;
while (*s) {
int digit;
char c = *s;
if (c >= '0' && c <= '9') digit = c - '0';
else if (c >= 'a' && c <= 'z') digit = c - 'a' + 10;
else if (c >= 'A' && c <= 'Z') digit = c - 'A' + 10;
else break;
if (digit >= base) break;
acc = acc * (unsigned)base + (unsigned)digit;
s++;
}
if (end) *end = (s == start) ? (char *)start : (char *)s;
if (neg) return -(long long)acc;
return (long long)acc;
}
+36
View File
@@ -0,0 +1,36 @@
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
unsigned long long strtoull(const char * restrict s, char ** restrict end, int base) {
while (*s == ' ' || *s == '\t') s++;
if (*s == '+') s++;
if (base == 0) {
if (*s == '0' && (s[1] == 'x' || s[1] == 'X')) { base = 16; s += 2; }
else if (*s == '0') { base = 8; s++; }
else { base = 10; }
} else if (base == 16 && *s == '0' && (s[1] == 'x' || s[1] == 'X')) {
s += 2;
}
unsigned long long acc = 0;
const char *start = s;
while (*s) {
int digit;
char c = *s;
if (c >= '0' && c <= '9') digit = c - '0';
else if (c >= 'a' && c <= 'z') digit = c - 'a' + 10;
else if (c >= 'A' && c <= 'Z') digit = c - 'A' + 10;
else break;
if (digit >= base) break;
acc = acc * (unsigned)base + (unsigned)digit;
s++;
}
if (end) *end = (s == start) ? (char *)start : (char *)s;
return acc;
}
+12
View File
@@ -0,0 +1,12 @@
#include <string.h>
void *memchr(void *ptr, int val, size_t n) {
const unsigned char *p = (const unsigned char*)ptr;
unsigned char c = (unsigned char)val;
for (size_t i = 0; i < n; i++) {
if (p[i] == c)
return (void*)(p + i);
}
return NULL;
}
+14
View File
@@ -0,0 +1,14 @@
#include <string.h>
int memcmp(const void *s1, const void *s2, size_t n) {
const uint8_t *p1 = (const uint8_t *)s1;
const uint8_t *p2 = (const uint8_t *)s2;
for (size_t i = 0; i < n; i++) {
if (p1[i] != p2[i]) {
return p1[i] < p2[i] ? -1 : 1;
}
}
return 0;
}
+12
View File
@@ -0,0 +1,12 @@
#include <string.h>
void *memcpy(void *restrict dest, const void *restrict src, size_t n) {
uint8_t *restrict pdest = (uint8_t *restrict)dest;
const uint8_t *restrict psrc = (const uint8_t *restrict)src;
for (size_t i = 0; i < n; i++) {
pdest[i] = psrc[i];
}
return dest;
}
+18
View File
@@ -0,0 +1,18 @@
#include <string.h>
void *memmove(void *dest, const void *src, size_t n) {
uint8_t *pdest = (uint8_t *)dest;
const uint8_t *psrc = (const uint8_t *)src;
if (src > dest) {
for (size_t i = 0; i < n; i++) {
pdest[i] = psrc[i];
}
} else if (src < dest) {
for (size_t i = n; i > 0; i--) {
pdest[i-1] = psrc[i-1];
}
}
return dest;
}
+11
View File
@@ -0,0 +1,11 @@
#include <string.h>
void *memset(void *s, int c, size_t n) {
uint8_t *p = (uint8_t *)s;
for (size_t i = 0; i < n; i++) {
p[i] = (uint8_t)c;
}
return s;
}
+7
View File
@@ -0,0 +1,7 @@
#include <string.h>
void* memset_explicit(void* dst, int c, size_t n) {
volatile unsigned char* p = (volatile unsigned char*)dst;
while (n--) *p++ = (unsigned char)c;
return dst;
}
+11
View File
@@ -0,0 +1,11 @@
#include <string.h>
void *rawmemchr(void *ptr, int val) {
const unsigned char *p = (const unsigned char*)ptr;
unsigned char c = (unsigned char)val;
for (;;) {
if (*p == c)
return (void*)p;
p++;
}
}
+17
View File
@@ -0,0 +1,17 @@
#include <string.h>
char *strcat(char *dest, const char *src) {
char *ptr = dest;
while (*ptr != '\0') {
ptr++;
}
while (*src != '\0') {
*ptr++ = *src++;
}
*ptr = '\0';
return dest;
}
+16
View File
@@ -0,0 +1,16 @@
#include <string.h>
char *strchr(const char *str, int c) {
char ch = (char)c;
while (*str) {
if (*str == ch)
return (char*)str;
str++;
}
if (ch == '\0')
return (char*)str;
return NULL;
}
+13
View File
@@ -0,0 +1,13 @@
#include <string.h>
int strcmp(const char *str1, const char *str2) {
size_t i = 0;
while (str1[i] != '\0' && str2[i] != '\0') {
if (str1[i] != str2[i])
goto ret;
i++;
}
ret:
return (unsigned char)str1[i] - (unsigned char)str2[i];
}
+7
View File
@@ -0,0 +1,7 @@
#include <string.h>
char *strcpy(char *dest, const char *src) {
char *p = dest;
while ((*p++ = *src++) != '\0') { }
return dest;
}
+11
View File
@@ -0,0 +1,11 @@
#include <string.h>
size_t strcspn(const char* s, const char* reject) {
size_t n = 0;
while (s[n]) {
for (const char* r = reject; *r; r++)
if (s[n] == *r) return n;
n++;
}
return n;
}
+9
View File
@@ -0,0 +1,9 @@
#include <string.h>
#include <stdlib.h>
char* strdup(const char* s) {
size_t len = strlen(s) + 1;
char* copy = malloc(len);
if (copy) memcpy(copy, s, len);
return copy;
}
+11
View File
@@ -0,0 +1,11 @@
#include <string.h>
size_t strlen(const char *str) {
size_t len = 0;
while (*str != '\0') {
len++;
str++;
}
return len;
}
+9
View File
@@ -0,0 +1,9 @@
#include <string.h>
char* strncat(char* restrict dst, const char* restrict src, size_t n) {
char* d = dst + strlen(dst);
while (n-- && *src)
*d++ = *src++;
*d = '\0';
return dst;
}
+18
View File
@@ -0,0 +1,18 @@
#include <string.h>
int strncmp(const char *str1, const char *str2, size_t n) {
size_t i = 0;
while (i < n) {
unsigned char c1 = (unsigned char)str1[i],
c2 = (unsigned char)str2[i];
if (c1 != c2)
return c1 - c2;
if (c1 == '\0')
return 0;
i++;
}
return 0;
}
+11
View File
@@ -0,0 +1,11 @@
#include <string.h>
char *strncpy(char *dest, const char *src, size_t n) {
size_t i = 0;
for (; i < n && src[i] != '\0'; i++)
dest[i] = src[i];
for (; i < n; i++)
dest[i] = '\0';
return dest;
}
+7
View File
@@ -0,0 +1,7 @@
#include <string.h>
size_t strnlen(const char* s, size_t maxlen) {
size_t n = 0;
while (n < maxlen && s[n]) n++;
return n;
}
+11
View File
@@ -0,0 +1,11 @@
#include <string.h>
char *strpbrk(const char *str1, const char *str2) {
for (; *str1 != '\0'; str1++) {
for (const char *p = str2; *p != '\0'; p++) {
if (*str1 == *p)
return (char*)str1;
}
}
return NULL;
}
+9
View File
@@ -0,0 +1,9 @@
#include <string.h>
char* strrchr(const char* s, int c) {
const char* last = NULL;
do {
if (*s == (char)c) last = s;
} while (*s++);
return (char*)last;
}
+24
View File
@@ -0,0 +1,24 @@
#include <string.h>
size_t strspn(const char *str1, const char *str2) {
size_t count = 0;
while (*str1) {
const char *p = str2;
int found = 0;
while (*p) {
if (*str1 == *p) {
found = 1;
break;
}
p++;
}
if (!found)
break;
count++;
str1++;
}
return count;
}
+17
View File
@@ -0,0 +1,17 @@
#include <string.h>
char *strstr(const char *haystack, const char *needle) {
if (*needle == '\0')
return (char*)haystack;
for (size_t i = 0; haystack[i] != '\0'; i++) {
size_t j = 0;
while (needle[j] != '\0' && haystack[j + i] == needle[j])
j++;
if (needle[j] == '\0')
return (char*)&haystack[i];
}
return NULL;
}
+22
View File
@@ -0,0 +1,22 @@
#include <string.h>
static char *old_string = NULL;
char *strtok(char *str, const char *delim) {
if (str == NULL) str = old_string;
str += strspn(str, delim);
if (*str == '\0') {
old_string = str;
return NULL;
}
char *token = str;
str = strpbrk(token, delim);
if (str == NULL)
old_string = rawmemchr(token, '\0');
else {
*str = '\0';
old_string = str + 1;
}
return token;
}
+39
View File
@@ -0,0 +1,39 @@
#include <string.h>
#include <ctype.h>
long strtol(const char* restrict s, char** restrict end, int base) {
while (isspace((unsigned char)*s)) s++;
int neg = 0;
if (*s == '-') { neg = 1; s++; }
else if (*s == '+') { s++; }
if ((base == 0 || base == 16) && s[0] == '0' &&
(s[1] == 'x' || s[1] == 'X')) {
base = 16;
s += 2;
} else if (base == 0 && s[0] == '0') {
base = 8;
s++;
} else if (base == 0) {
base = 10;
}
long result = 0;
int any = 0;
for (; *s; s++) {
int digit;
unsigned char c = (unsigned char)*s;
if (isdigit(c)) digit = c - '0';
else if (isupper(c)) digit = c - 'A' + 10;
else if (islower(c)) digit = c - 'a' + 10;
else break;
if (digit >= base) break;
result = result * base + digit;
any = 1;
}
if (end) *end = (char*)(any ? s : (const char*)s);
return neg ? -result : result;
}
+37
View File
@@ -0,0 +1,37 @@
#include <string.h>
#include <ctype.h>
unsigned long strtoul(const char* restrict s, char** restrict end, int base) {
while (isspace((unsigned char)*s)) s++;
if (*s == '+') s++;
if ((base == 0 || base == 16) && s[0] == '0' &&
(s[1] == 'x' || s[1] == 'X')) {
base = 16;
s += 2;
} else if (base == 0 && s[0] == '0') {
base = 8;
s++;
} else if (base == 0) {
base = 10;
}
unsigned long result = 0;
int any = 0;
for (; *s; s++) {
int digit;
unsigned char c = (unsigned char)*s;
if (isdigit(c)) digit = c - '0';
else if (isupper(c)) digit = c - 'A' + 10;
else if (islower(c)) digit = c - 'a' + 10;
else break;
if (digit >= base) break;
result = result * (unsigned long)base + (unsigned long)digit;
any = 1;
}
if (end) *end = (char*)(any ? s : (const char*)s);
return result;
}