diff --git a/components/libc/include/ctype.h b/components/libc/include/ctype.h new file mode 100644 index 0000000..fc4d866 --- /dev/null +++ b/components/libc/include/ctype.h @@ -0,0 +1,41 @@ +#ifndef __CTYPE_H +#define __CTYPE_H + +#ifdef __cplusplus +extern "C" { +#endif + +int iscntrl(int c); + +int isblank(int c); + +int isspace(int c); + +int isupper(int c); + +int islower(int c); + +int isalpha(int c); + +int isdigit(int c); + +int isxdigit(int c); + +int isalnum(int c); + +int ispunct(int c); + +int isgraph(int c); + +int isprint(int c); + +int tolower(int c); + +int toupper(int c); + +#ifdef __cplusplus +} +#endif + +#endif /* __CTYPE_H */ + diff --git a/components/libc/include/stdio.h b/components/libc/include/stdio.h index 28b3571..d320089 100644 --- a/components/libc/include/stdio.h +++ b/components/libc/include/stdio.h @@ -3,12 +3,15 @@ #include #include -#include "hal_sys_uart.h" #ifdef __cplusplus extern "C" { #endif +int putchar(int c); + +int puts(const char *str); + /** * @brief Formatted output to stdout * @param fmt Format string diff --git a/components/libc/include/stdlib.h b/components/libc/include/stdlib.h new file mode 100644 index 0000000..591970e --- /dev/null +++ b/components/libc/include/stdlib.h @@ -0,0 +1,49 @@ +#ifndef __STDLIB_H +#define __STDLIB_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + void* start; + void* end; +} area_t; + +extern const area_t heap; + +__attribute__ ((__noreturn__)) +void halt(int code); + +#ifndef NULL +#define NULL 0 +#endif + +#define RAND_MAX 0x7fffffff; + +void srand(unsigned int seed); + +int rand(void); + +void *malloc(size_t size); + +void free(void *ptr); + +int abs(int x); + +int atoi(const char *nptr); + +__attribute__ ((__noreturn__)) +void exit(int code); + +__attribute__ ((__noreturn__)) +void abort(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __STDLIB_H */ diff --git a/components/libc/include/string.h b/components/libc/include/string.h index dcdb3e9..3538784 100644 --- a/components/libc/include/string.h +++ b/components/libc/include/string.h @@ -33,7 +33,7 @@ void* memset(void* s, int c, size_t n); */ size_t strlen(const char* s); -size_t memcmp(const void* ptr1, const void* ptr2, size_t num); +int memcmp(const void* ptr1, const void* ptr2, size_t num); char* strchr(const char* str, int c); diff --git a/components/libc/src/ctype.c b/components/libc/src/ctype.c new file mode 100644 index 0000000..ad87736 --- /dev/null +++ b/components/libc/src/ctype.c @@ -0,0 +1,68 @@ +#include "ctype.h" + +int iscntrl(int c) { + return (c >= '\0' && c <= '\x1f') || (c == '\x7f'); +} + +int isblank(int c) { + return (c == '\t' || c == ' '); +} + +int isspace(int c) { + return (c == ' ' || (c >= '\t' && c <= '\r')); +} + +int isupper(int c) { + return (c >= 'A' && c <= 'Z'); +} + +int islower(int c) { + return (c >= 'a' && c <= 'z'); +} + +int isalpha(int c) { + return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); +} + +int isdigit(int c) { + return (c >= '0' && c <= '9'); +} + +int isxdigit(int c) { + return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'); +} + +int isalnum(int c) { + return (c >= '0' && c <= '9') || (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'); +} + +int ispunct(int c) { + return (c >= '!' && c <= '/') || + (c >= ':' && c <= '@') || + (c >= '[' && c <= '`') || + (c >= '{' && c <= '~'); +} + +int isgraph(int c) { + return (c >= '!' && c <= '~'); +} + +int isprint(int c) { + return (c >= ' ' && c <= '~'); +} + +int tolower(int c) { + if (isupper(c)) { + return c - 'A' + 'a'; + } else { + return c; + } +} + +int toupper(int c) { + if (islower(c)) { + return c - 'a' + 'A'; + } else { + return c; + } +} diff --git a/components/libc/src/stdio.c b/components/libc/src/stdio.c index 3eb7bcb..92eed37 100644 --- a/components/libc/src/stdio.c +++ b/components/libc/src/stdio.c @@ -1,455 +1,455 @@ +#include +#include +#include +#include #include "stdio.h" #include "string.h" +#include "hal_sys_uart.h" -// 辅助函数:输出字符串 -static int puts_helper(const char *str) { - int count = 0; - while (*str) { - hal_sys_putchar(*str++); - count++; +int putchar(int c) { + char ch = c; + hal_sys_putchar(c); + return ch; +} + +int puts(const char *str) { + int cnt; + for (cnt=0; str[cnt]; ++cnt) { + hal_sys_putchar(str[cnt]); } + hal_sys_putchar('\n'); + return cnt; +} + +typedef struct { + char *dest; // if putch is NULL, write to this memory address + void (*putch)(char ch); // the function to write a character + size_t count; // number of charactors written, SIZE_MAX indicates an error + size_t max_count; // max number of characters to write +} printf_state_t; + +static void printf_backend(printf_state_t *state, const char *fmt, va_list ap); + +int printf(const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + printf_state_t state = { + .dest = NULL, + .count = 0, + .max_count = SIZE_MAX, + .putch = hal_sys_putchar, + }; + printf_backend(&state, fmt, ap); + va_end(ap); + return state.count; +} + +int vsprintf(char *out, const char *fmt, va_list ap) { return vsnprintf(out, SIZE_MAX, fmt, ap); } + +int sprintf(char *out, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + int count = vsnprintf(out, SIZE_MAX, fmt, ap); + va_end(ap); return count; } -// 辅助函数:将整数转换为字符串(十进制) -static int itoa_decimal(int value, char *buffer, int min_width, char pad_char) { - char temp[12]; // 足够存储 32 位整数 - int i = 0; - int is_negative = 0; - - if (value < 0) { - is_negative = 1; - value = -value; - } - - if (value == 0) { - temp[i++] = '0'; - } else { - while (value > 0) { - temp[i++] = '0' + (value % 10); - value /= 10; +int snprintf(char *out, size_t n, const char *fmt, ...) { + va_list ap; + va_start(ap, fmt); + int count = vsnprintf(out, n, fmt, ap); + va_end(ap); + return count; +} + +int vsnprintf(char *out, size_t n, const char *fmt, va_list ap) { + printf_state_t state = { + .dest = out, + .count = 0, + .max_count = SIZE_MAX, + .putch = NULL, + }; + printf_backend(&state, fmt, ap); + return state.count; +} + +static void printf_putch(printf_state_t *state, char ch) { + if (state->count < state->max_count) { + if (state->putch != NULL) { + state->putch(ch); + } else { + state->dest[state->count] = ch; } } - - int len = 0; - if (is_negative && pad_char == '0') { - buffer[len++] = '-'; + state->count += 1; +} + +static void printf_pad(printf_state_t *state, char ch, size_t n) { + for (size_t i = 0; i < n; ++i) { + printf_putch(state, ch); } +} - while (i + is_negative < min_width) { - buffer[len++] = pad_char; - min_width--; +static void printf_char(printf_state_t *state, char ch, size_t width, int left_justified) { + if (left_justified) { + printf_putch(state, ch); + if (width > 1) { + printf_pad(state, ' ', width - 1); + } + } else { + if (width > 1) { + printf_pad(state, ' ', width - 1); + } + printf_putch(state, ch); } +} - if (is_negative && pad_char != '0') { - buffer[len++] = '-'; +static void printf_string(printf_state_t *state, const char *str, size_t width, int left_justified) { + size_t len = strlen(str); + if (width > len && !left_justified) { + printf_pad(state, ' ', width - len); + } + for (size_t i = 0; str[i]; ++i) { + printf_putch(state, str[i]); } - - // 反转数字 - while (i > 0) { - buffer[len++] = temp[--i]; + if (width > len && left_justified) { + printf_pad(state, ' ', width - len); } - buffer[len] = '\0'; - - return len; } -// 辅助函数:将整数转换为十六进制字符串 -static int itoa_hex(unsigned long value, char *buffer, int uppercase, int min_width, char pad_char) { - char temp[17]; // 足够存储 64 位十六进制 - int i = 0; - const char *digits = uppercase ? "0123456789ABCDEF" : "0123456789abcdef"; - - if (value == 0) { - temp[i++] = '0'; +static void printf_uint32(printf_state_t *state, unsigned int n, size_t width, int left_justified, char padding) { + unsigned int n_digits = 0; + char buffer[10] = { + '0', + }; + if (n == 0) { + buffer[0] = '0'; + n_digits = 1; } else { - while (value > 0) { - temp[i++] = digits[value % 16]; - value /= 16; + while (n > 0) { + buffer[n_digits] = n % 10 + '0'; + n_digits += 1; + n /= 10; } } - - int len = 0; - while (i < min_width) { - buffer[len++] = pad_char; - min_width--; + if (!left_justified && width > n_digits) { + printf_pad(state, padding, width - n_digits); } - - // 反转数字 - while (i > 0) { - buffer[len++] = temp[--i]; + for (int i = n_digits - 1; i >= 0; --i) { + printf_putch(state, buffer[i]); + } + if (left_justified && width > n_digits) { + printf_pad(state, ' ', width - n_digits); } - buffer[len] = '\0'; - - return len; } -// vprintf 实现 -int vprintf(const char *fmt, va_list args) { - int count = 0; - char buffer[32]; - - while (*fmt) { - if (*fmt == '%' && *(fmt + 1)) { - fmt++; // 跳过 '%' - - char pad_char = ' '; - int min_width = 0; - - // 解析前导零 - if (*fmt == '0') { - pad_char = '0'; - fmt++; - } - - // 解析宽度 - while (*fmt >= '0' && *fmt <= '9') { - min_width = min_width * 10 + (*fmt - '0'); - fmt++; - } - - switch (*fmt) { - case 'c': { - // 字符 - char c = (char)va_arg(args, int); - hal_sys_putchar(c); - count++; - break; - } - - case 's': { - // 字符串 - const char *str = va_arg(args, const char*); - if (str == NULL) { - str = "(null)"; - } - count += puts_helper(str); - break; - } - - case 'd': - case 'i': { - // 十进制整数 - int value = va_arg(args, int); - int len = itoa_decimal(value, buffer, min_width, pad_char); - count += puts_helper(buffer); - break; - } - - case 'u': { - // 无符号十进制整数 - unsigned int value = va_arg(args, unsigned int); - int len = itoa_decimal((int)value, buffer, min_width, pad_char); // 简化处理 - count += puts_helper(buffer); - break; - } - - case 'x': { - // 小写十六进制 - unsigned int value = va_arg(args, unsigned int); - int len = itoa_hex(value, buffer, 0, min_width, pad_char); - count += puts_helper(buffer); - break; - } - - case 'X': { - // 大写十六进制 - unsigned int value = va_arg(args, unsigned int); - int len = itoa_hex(value, buffer, 1, min_width, pad_char); - count += puts_helper(buffer); - break; - } - - case 'p': { - // 指针(作为十六进制处理) - void *ptr = va_arg(args, void*); - hal_sys_putchar('0'); - hal_sys_putchar('x'); - count += 2; - int len = itoa_hex((unsigned long)ptr, buffer, 0, min_width, pad_char); - count += puts_helper(buffer); - break; - } - - case '%': { - // 字面量 '%' - hal_sys_putchar('%'); - count++; - break; - } +static void printf_int32(printf_state_t *state, int n, size_t width, int left_justified, char padding, char sign) { + if (sign && n > 0) { + printf_putch(state, sign); + width -= 1; + } else if (n < 0) { + printf_putch(state, '-'); + n = -n; + width -= 1; + } + printf_uint32(state, n, width, left_justified, padding); +} - case 'l': { - // 长整数处理 (简化) - fmt++; - if (*fmt == 'l') { - fmt++; - } - if (*fmt == 'x' || *fmt == 'X') { - unsigned long value = va_arg(args, unsigned long); - int len = itoa_hex(value, buffer, *fmt == 'X', min_width, pad_char); - count += puts_helper(buffer); - } else if (*fmt == 'd' || *fmt == 'i' || *fmt == 'u') { - long value = va_arg(args, long); - int len = itoa_decimal(value, buffer, min_width, pad_char); - count += puts_helper(buffer); - } else { - hal_sys_putchar('%'); - hal_sys_putchar(*fmt); - count += 2; - } - break; - } - - default: { - // 不支持的格式,输出原样 - hal_sys_putchar('%'); - hal_sys_putchar(*fmt); - count += 2; - break; - } - } - } else { - // 普通字符 - hal_sys_putchar(*fmt); - count++; +static void printf_uint64(printf_state_t *state, unsigned long long int n, size_t width, int left_justified, char padding) { + unsigned int n_digits = 0; + char buffer[20] = { + '0', + }; + if (n == 0) { + buffer[0] = '0'; + n_digits = 1; + } else { + while (n > 0) { + buffer[n_digits] = n % 10 + '0'; + n_digits += 1; + n /= 10; } - fmt++; } - - return count; + if (!left_justified && width > n_digits) { + printf_pad(state, padding, width - n_digits); + } + for (int i = n_digits - 1; i >= 0; --i) { + printf_putch(state, buffer[i]); + } + if (left_justified && width > n_digits) { + printf_pad(state, ' ', width - n_digits); + } } - - -// vsnprintf 实现 -int vsnprintf(char *str, size_t size, const char *fmt, va_list args) { - if (size == 0) { - return 0; +static void printf_int64(printf_state_t *state, long long int n, size_t width, int left_justified, char padding, char sign) { + if (sign && n > 0) { + printf_putch(state, sign); + width -= 1; + } else if (n < 0) { + printf_putch(state, '-'); + n = -n; + width -= 1; } + printf_uint64(state, n, width, left_justified, padding); +} - int count = 0; // 应该写入的总字符数(不含结尾 '\0') - char *dest = str; - char buffer[32]; // 用于临时存储整数/十六进制转换的缓冲区 - size_t remaining = size - 1; // 留一个位置给 '\0' +static void printf_hex32(printf_state_t *state, unsigned int n, size_t width, int left_justified, char padding, int upper_case) { + char buffer[8] = { + '0', + }; + unsigned int n_digits = 0; + if (n == 0) { + buffer[0] = '0'; + n_digits = 1; + } else { + while (n > 0) { + unsigned int rem = n % 16; + buffer[n_digits++] = (rem < 10) ? (rem + '0') : (rem - 10 + (upper_case ? 'A' : 'a')); + n /= 16; + } + } + if (!left_justified && width > n_digits) { + printf_pad(state, padding, width - n_digits); + } + for (int i = n_digits - 1; i >= 0; --i) { + printf_putch(state, buffer[i]); + } + if (left_justified && width > n_digits) { + printf_pad(state, ' ', width - n_digits); + } +} - while (*fmt) { - if (*fmt == '%' && *(fmt + 1)) { - fmt++; // 跳过 '%' +static void printf_hex64(printf_state_t *state, unsigned long long int n, size_t width, int left_justified, char padding, int upper_case) { + char buffer[16] = { + '0', + }; + unsigned int n_digits = 0; - char pad_char = ' '; - int min_width = 0; + if (n == 0) { + buffer[0] = '0'; + n_digits = 1; + } else { + while (n > 0) { + unsigned int rem = n % 16; + buffer[n_digits++] = (rem < 10) ? (rem + '0') : (rem - 10 + (upper_case ? 'A' : 'a')); + n /= 16; + } + } + if (!left_justified && width > n_digits) { + printf_pad(state, padding, width - n_digits); + } + for (int i = n_digits - 1; i >= 0; --i) { + printf_putch(state, buffer[i]); + } + if (left_justified && width > n_digits) { + printf_pad(state, ' ', width - n_digits); + } +} - // 解析前导零 - if (*fmt == '0') { - pad_char = '0'; - fmt++; - } +static void printf_octal32(printf_state_t *state, unsigned int n, size_t width, int left_justified, char padding) { + char buffer[11] = { + '0', + }; + unsigned int n_digits = 0; + if (n == 0) { + buffer[0] = '0'; + n_digits = 1; + } else { + while (n > 0) { + unsigned int rem = n % 8; + buffer[n_digits++] = rem + '0'; + n /= 8; + } + } + if (!left_justified && width > n_digits) { + printf_pad(state, padding, width - n_digits); + } + for (int i = n_digits - 1; i >= 0; --i) { + printf_putch(state, buffer[i]); + } + if (left_justified && width > n_digits) { + printf_pad(state, ' ', width - n_digits); + } +} - // 解析宽度 - while (*fmt >= '0' && *fmt <= '9') { - min_width = min_width * 10 + (*fmt - '0'); - fmt++; - } +static void printf_octal64(printf_state_t *state, unsigned long long int n, size_t width, int left_justified, char padding) { + char buffer[22] = { + '0', + }; + unsigned int n_digits = 0; + if (n == 0) { + buffer[0] = '0'; + n_digits = 1; + } else { + while (n > 0) { + unsigned int rem = n % 8; + buffer[n_digits++] = rem + '0'; + n /= 8; + } + } + if (!left_justified && width > n_digits) { + printf_pad(state, padding, width - n_digits); + } + for (int i = n_digits - 1; i >= 0; --i) { + printf_putch(state, buffer[i]); + } + if (left_justified && width > n_digits) { + printf_pad(state, ' ', width - n_digits); + } +} - switch (*fmt) { - case 'c': { - char c = (char)va_arg(args, int); - if (remaining > 0) { - *dest++ = c; - remaining--; - } - count++; +static void printf_backend(printf_state_t *state, const char *fmt, va_list ap) { + const size_t n = strlen(fmt) + 1; + for (size_t i = 0; i < n; ++i) { + if (fmt[i] == '%') { + // parse the %specifier + // see https://en.cppreference.com/w/c/io/fprintf + ++i; + // parse the flags + int left_justified = 0; + char sign = '\0'; + char padding = ' '; + while (1) { + char flag = fmt[i]; + if (flag == '-') { + left_justified = 1; + } else if (flag == '+') { + sign = '+'; + } else if (flag == ' ') { + sign = ' '; + } else if (flag == '0') { + padding = '0'; + } else if (flag == '#') { + // not implemented + } else { break; } - - case 's': { - const char *src = va_arg(args, const char*); - if (src == NULL) { - src = "(null)"; - } - while (*src) { - if (remaining > 0) { - *dest++ = *src; - remaining--; - } - count++; - src++; - } + ++i; + } + // parse the width + size_t width = 0; + while (fmt[i] >= '0' && fmt[i] <= '9') { + width *= 10; + width += fmt[i] - '0'; + ++i; + } + // parse the precision + if (fmt[i] == '.') { + // not implemented, skip only + while (fmt[i] >= '0' && fmt[i] <= '9') { + ++i; + } + } + // parse the length + int length_level = 0; + while (1) { + if (fmt[i] == 'l') { + length_level += 1; + } else if (fmt[i] == 'h') { + length_level -= 1; + } else { break; } - - case 'd': - case 'i': { - int value = va_arg(args, int); - int len = itoa_decimal(value, buffer, min_width, pad_char); - for (int i = 0; i < len; i++) { - if (remaining > 0) { - *dest++ = buffer[i]; - remaining--; - } - count++; - } + ++i; + } + // parse the parameter type + switch (fmt[i]) { + case '%': + printf_char(state, '%', width, left_justified); + break; + case 'c': { + char ch = (char)va_arg(ap, int); + printf_char(state, ch, width, left_justified); break; } - - case 'u': { - unsigned int value = va_arg(args, unsigned int); - int len = itoa_decimal((int)value, buffer, min_width, pad_char); - for (int i = 0; i < len; i++) { - if (remaining > 0) { - *dest++ = buffer[i]; - remaining--; - } - count++; - } + case 's': { + char *str = (char *)va_arg(ap, void *); + printf_string(state, str, width, left_justified); break; } - - case 'x': { - unsigned int value = va_arg(args, unsigned int); - int len = itoa_hex(value, buffer, 0, min_width, pad_char); - for (int i = 0; i < len; i++) { - if (remaining > 0) { - *dest++ = buffer[i]; - remaining--; - } - count++; + case 'd': + case 'i': + if (length_level <= 0) { + // short and byte are padded into int when passed with `...` + int n = va_arg(ap, int); + printf_int32(state, n, width, left_justified, padding, sign); + } else if (length_level == 1 && sizeof(long) * CHAR_BIT == 32) { + long int n = va_arg(ap, long int); + printf_int32(state, n, width, left_justified, padding, sign); + } else if (length_level == 1 && sizeof(long) * CHAR_BIT == 64) { + long int n = va_arg(ap, long int); + printf_int64(state, n, width, left_justified, padding, sign); + } else { + long long int n = va_arg(ap, long long int); + printf_int64(state, n, width, left_justified, padding, sign); } break; - } - - case 'X': { - unsigned int value = va_arg(args, unsigned int); - int len = itoa_hex(value, buffer, 1, min_width, pad_char); - for (int i = 0; i < len; i++) { - if (remaining > 0) { - *dest++ = buffer[i]; - remaining--; - } - count++; + case 'u': + if (length_level <= 0) { + // short and byte are padded into int when passed with `...` + unsigned int n = va_arg(ap, unsigned int); + printf_uint32(state, n, width, left_justified, padding); + } else if (length_level == 1 && sizeof(long) * CHAR_BIT == 32) { + unsigned long int n = va_arg(ap, unsigned long int); + printf_uint32(state, n, width, left_justified, padding); + } else if (length_level == 1 && sizeof(long) * CHAR_BIT == 64) { + unsigned long int n = va_arg(ap, unsigned long int); + printf_uint64(state, n, width, left_justified, padding); + } else { + unsigned long long int n = va_arg(ap, unsigned long long int); + printf_uint64(state, n, width, left_justified, padding); } break; - } - + case 'x': + case 'X': case 'p': { - void *ptr = va_arg(args, void*); - // 处理 "0x" 前缀 - if (remaining > 0) { - *dest++ = '0'; - remaining--; - } - count++; - if (remaining > 0) { - *dest++ = 'x'; - remaining--; - } - count++; - int len = itoa_hex((unsigned long)ptr, buffer, 0, min_width, pad_char); - for (int i = 0; i < len; i++) { - if (remaining > 0) { - *dest++ = buffer[i]; - remaining--; + int upper_case = (fmt[i] == 'X'); + if (length_level <= 0) { + unsigned int n = va_arg(ap, unsigned int); + printf_hex32(state, n, width, left_justified, padding, upper_case); + } else if (length_level == 1) { + unsigned long int n = va_arg(ap, unsigned long int); + if (sizeof(unsigned long) * CHAR_BIT == 32) { + printf_hex32(state, n, width, left_justified, padding, upper_case); + } else { + printf_hex64(state, n, width, left_justified, padding, upper_case); } - count++; - } - break; - } - - case '%': { - if (remaining > 0) { - *dest++ = '%'; - remaining--; + } else { + unsigned long long int n = va_arg(ap, unsigned long long int); + printf_hex64(state, n, width, left_justified, padding, upper_case); } - count++; break; } - - case 'l': { - fmt++; - if (*fmt == 'l') { - fmt++; - } - if (*fmt == 'x' || *fmt == 'X') { - unsigned long value = va_arg(args, unsigned long); - int len = itoa_hex(value, buffer, (*fmt == 'X'), min_width, pad_char); - for (int i = 0; i < len; i++) { - if (remaining > 0) { - *dest++ = buffer[i]; - remaining--; - } - count++; - } - } else if (*fmt == 'd' || *fmt == 'i' || *fmt == 'u') { - long value = va_arg(args, long); - int len = itoa_decimal(value, buffer, min_width, pad_char); - for (int i = 0; i < len; i++) { - if (remaining > 0) { - *dest++ = buffer[i]; - remaining--; - } - count++; + case 'o': + if (length_level <= 0) { + unsigned int n = va_arg(ap, unsigned int); + printf_octal32(state, n, width, left_justified, padding); + } else if (length_level == 1) { + unsigned long int n = va_arg(ap, unsigned long int); + if (sizeof(unsigned long) * CHAR_BIT == 32) { + printf_octal32(state, n, width, left_justified, padding); + } else { + printf_octal64(state, n, width, left_justified, padding); } } else { - if (remaining > 0) { - *dest++ = '%'; - remaining--; - } - count++; - if (remaining > 0) { - *dest++ = *fmt; - remaining--; - } - count++; + unsigned long long int n = va_arg(ap, unsigned long long int); + printf_octal64(state, n, width, left_justified, padding); } break; - } - - default: { - if (remaining > 0) { - *dest++ = '%'; - remaining--; - } - count++; - if (remaining > 0) { - *dest++ = *fmt; - remaining--; - } - count++; + case 'f': + case 'F': + case 'e': + case 'E': + case 'g': + case 'G': + case 'a': + case 'A': + // not implemented, skip only + va_arg(ap, double); break; - } } } else { - if (remaining > 0) { - *dest++ = *fmt; - remaining--; - } - count++; + printf_putch(state, fmt[i]); } - fmt++; } - - *dest = '\0'; // 添加字符串终止符 - return count; } - -int snprintf(char *buffer, size_t size, const char *format, ...){ - va_list args; - int result; - - va_start(args, format); - result = vsnprintf(buffer, size, format, args); - va_end(args); - - return result; -} - -// printf 实现 -int printf(const char *fmt, ...) { - va_list args; - va_start(args, fmt); - int ret = vprintf(fmt, args); - va_end(args); - return ret; -} - - diff --git a/components/libc/src/stdlib.c b/components/libc/src/stdlib.c new file mode 100644 index 0000000..7f0a83b --- /dev/null +++ b/components/libc/src/stdlib.c @@ -0,0 +1,375 @@ +#include "ctype.h" +#include "stdlib.h" + +static unsigned int _random_seed = 0x7a2d5eed; + +int rand(void) { + unsigned int feedback = 0; + feedback ^= (_random_seed>>31) | 1; + feedback ^= (_random_seed>>21) | 1; + feedback ^= (_random_seed>>1) | 1; + feedback ^= (_random_seed>>0) | 1; + _random_seed >>= 1; + _random_seed |= feedback<<31; + return (_random_seed >> 1) % RAND_MAX; +} + +void srand(unsigned int seed) { + _random_seed = seed; +} + +int abs(int x) { + return (x < 0 ? -x : x); +} + +int atoi(const char* nptr) { + int x = 0; + int negative = 0; + while (isspace(*nptr)) { + nptr++; + } + if (*nptr == '+') { + negative = 0; + ++nptr; + } else if (*nptr == '-') { + negative = 1; + ++nptr; + } + while (*nptr >= '0' && *nptr <= '9') { + x = x * 10 + *nptr - '0'; + nptr ++; + } + if (negative) { + return -x; + } else { + return x; + } +} + +long int atol(const char* nptr) { + long int x = 0; + int negative = 0; + while (isspace(*nptr)) { + nptr++; + } + if (*nptr == '+') { + negative = 0; + ++nptr; + } else if (*nptr == '-') { + negative = 1; + ++nptr; + } + while (*nptr >= '0' && *nptr <= '9') { + x = x * 10 + *nptr - '0'; + nptr ++; + } + if (negative) { + return -x; + } else { + return x; + } +} + +long long int atoll(const char* nptr) { + long long int x = 0; + int negative = 0; + while (isspace(*nptr)) { + nptr++; + } + if (*nptr == '+') { + negative = 0; + ++nptr; + } else if (*nptr == '-') { + negative = 1; + ++nptr; + } + while (*nptr >= '0' && *nptr <= '9') { + x = x * 10 + *nptr - '0'; + nptr ++; + } + if (negative) { + return -x; + } else { + return x; + } +} + +long int strtol(const char* str, char** endptr, int base) { + size_t i = 0; + int negative = 0; + long int result = 0; + // fail if `base` is invalid + if (base!=0 && (base<2 || base>36)) { + goto finish; + } + // skip all whitespaces + while (isspace(str[i])) { + ++i; + } + // detect sign + if (str[i] == '+') { + negative = 0; + ++i; + } else if (str[i] == '-') { + negative = 1; + ++i; + } + // detect base + if (base == 0) { + if (str[i] == '0') { + ++i; + if (str[i]=='x' || str[i]=='X') { + base = 16; + ++i; + } else { + base = 8; + } + } else { + base = 10; + } + } else if (base == 16) { + // sikp the "0x" prefix for hexadecimal + if (str[i] == '0') { + ++i; + } + if (str[i]=='x' || str[i]=='X') { + ++i; + } + } + // parse number + while (1) { + long int digit; + if (isdigit(str[i])) { + digit = str[i] - '0'; + } else if (isupper(str[i])) { + digit = str[i] - 'A' + 10; + } else if (islower(str[i])) { + digit = str[i] - 'a' + 10; + } else { + break; + } + if (digit >= base) { + break; + } + result *= base; + result += digit; + ++i; + } + finish: + if (endptr != NULL) { + *endptr = (char*)str + i; + } + if (negative) { + return -result; + } else { + return result; + } +} + +long long int strtoll(const char* str, char** endptr, int base) { + size_t i = 0; + int negative = 0; + long long int result = 0; + // fail if `base` is invalid + if (base!=0 && (base<2 || base>36)) { + goto finish; + } + // skip all whitespaces + while (isspace(str[i])) { + ++i; + } + // detect sign + if (str[i] == '+') { + negative = 0; + ++i; + } else if (str[i] == '-') { + negative = 1; + ++i; + } + // detect base + if (base == 0) { + if (str[i] == '0') { + ++i; + if (str[i]=='x' || str[i]=='X') { + base = 16; + ++i; + } else { + base = 8; + } + } else { + base = 10; + } + } else if (base == 16) { + // sikp the "0x" prefix for hexadecimal + if (str[i] == '0') { + ++i; + } + if (str[i]=='x' || str[i]=='X') { + ++i; + } + } + // parse number + while (1) { + long int digit; + if (isdigit(str[i])) { + digit = str[i] - '0'; + } else if (isupper(str[i])) { + digit = str[i] - 'A' + 10; + } else if (islower(str[i])) { + digit = str[i] - 'a' + 10; + } else { + break; + } + if (digit >= base) { + break; + } + result *= base; + result += digit; + ++i; + } + finish: + if (endptr != NULL) { + *endptr = (char*)str + i; + } + if (negative) { + return -result; + } else { + return result; + } +} + +unsigned long int strtoul(const char* str, char** endptr, int base) { + size_t i = 0; + unsigned long int result = 0; + // fail if `base` is invalid + if (base!=0 && (base<2 || base>36)) { + goto finish; + } + // skip all whitespaces + while (isspace(str[i])) { + ++i; + } + // detect base + if (base == 0) { + if (str[i] == '0') { + ++i; + if (str[i]=='x' || str[i]=='X') { + base = 16; + ++i; + } else { + base = 8; + } + } else { + base = 10; + } + } else if (base == 16) { + // sikp the "0x" prefix for hexadecimal + if (str[i] == '0') { + ++i; + } + if (str[i]=='x' || str[i]=='X') { + ++i; + } + } + // parse number + while (1) { + long int digit; + if (isdigit(str[i])) { + digit = str[i] - '0'; + } else if (isupper(str[i])) { + digit = str[i] - 'A' + 10; + } else if (islower(str[i])) { + digit = str[i] - 'a' + 10; + } else { + break; + } + if (digit >= base) { + break; + } + result *= base; + result += digit; + ++i; + } + finish: + if (endptr != NULL) { + *endptr = (char*)str + i; + } + return result; +} + +unsigned long long int strtoull(const char* str, char** endptr, int base) { + size_t i = 0; + unsigned long long int result = 0; + // fail if `base` is invalid + if (base!=0 && (base<2 || base>36)) { + goto finish; + } + // skip all whitespaces + while (isspace(str[i])) { + ++i; + } + // detect base + if (base == 0) { + if (str[i] == '0') { + ++i; + if (str[i]=='x' || str[i]=='X') { + base = 16; + ++i; + } else { + base = 8; + } + } else { + base = 10; + } + } else if (base == 16) { + // sikp the "0x" prefix for hexadecimal + if (str[i] == '0') { + ++i; + } + if (str[i]=='x' || str[i]=='X') { + ++i; + } + } + // parse number + while (1) { + long int digit; + if (isdigit(str[i])) { + digit = str[i] - '0'; + } else if (isupper(str[i])) { + digit = str[i] - 'A' + 10; + } else if (islower(str[i])) { + digit = str[i] - 'a' + 10; + } else { + break; + } + if (digit >= base) { + break; + } + result *= base; + result += digit; + ++i; + } + finish: + if (endptr != NULL) { + *endptr = (char*)str + i; + } + return result; +} + +void *malloc(size_t size) { + return NULL; +} + +void free(void *ptr) { + return; +} + +__attribute__ ((__noreturn__)) +void exit(int code) { + while (1); +} + +__attribute__ ((__noreturn__)) +void abort(void) { + while (1); +} diff --git a/components/libc/src/string.c b/components/libc/src/string.c index 246b779..6b84d8b 100644 --- a/components/libc/src/string.c +++ b/components/libc/src/string.c @@ -33,18 +33,16 @@ size_t strlen(const char *s) { return len; } -size_t memcmp(const void* ptr1, const void* ptr2, size_t num) { - const unsigned char* p1 = (const unsigned char*)ptr1; - const unsigned char* p2 = (const unsigned char*)ptr2; - - while (num--) { - if (*p1 != *p2) { - return (*p1 - *p2); +int memcmp(const void* ptr1, const void* ptr2, size_t num) { + const unsigned char *p1 = (const unsigned char*)ptr1; + const unsigned char *p2 = (const unsigned char*)ptr2; + for (size_t i=0; i p2[i]) { + return 1; + } else if (p1[i] < p2[i]) { + return -1; } - p1++; - p2++; } - return 0; }