diff --git a/kernel/printk.c b/kernel/printk.c index a6191a51..9a83e9b7 100644 --- a/kernel/printk.c +++ b/kernel/printk.c @@ -2,6 +2,7 @@ // Created by longjin on 2022/1/22. // #include "printk.h" +#include int skip_and_atoi(const char **s) { @@ -17,7 +18,7 @@ int skip_and_atoi(const char **s) } return ans; } -int vsprintf(char *buf, const char *fmt, va_list args) +static int vsprintf(char *buf, const char *fmt, va_list args) { /** * 将字符串按照fmt和args中的内容进行格式化,然后保存到buf中 @@ -45,6 +46,7 @@ int vsprintf(char *buf, const char *fmt, va_list args) { *str = *fmt; ++str; + continue; } //开始格式化字符串 @@ -164,6 +166,7 @@ int vsprintf(char *buf, const char *fmt, va_list args) } break; + //显示一个字符串 case 's': s = va_arg(args, char *); @@ -188,7 +191,7 @@ int vsprintf(char *buf, const char *fmt, va_list args) *str = ' '; ++str; } - + for (int i = 0; i < len; i++) { *str = *s; @@ -196,17 +199,183 @@ int vsprintf(char *buf, const char *fmt, va_list args) ++str; } - while (len 36) + return 0; + + char pad, sign, tmp_num[100]; + + const char *digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + // 显示小写字母 + if (flags & SMALL) + digits = "0123456789abcdefghijklmnopqrstuvwxyz"; + + // 设置填充元素 + pad = (flags & PAD_ZERO) ? '0' : ' '; + + sign = 0; + if (flags & SIGN && num < 0) + { + sign = '-'; + num = -num; + } + else + { + // 设置符号 + sign = (flags & PLUS) ? '+' : ((flags & SPACE) ? ' ' : 0); + } + + // sign占用了一个宽度 + if (sign) + --field_width; + + if (flags & SPECIAL) + if (base == 16) // 0x占用2个位置 + field_width -= 2; + else if (base == 8) // O占用一个位置 + --field_width; + + int js_num = 0; // 临时数字字符串tmp_num的长度 + + if (num == 0) + tmp_num[js_num++] = '0'; + else + { + num = abs(num); + //进制转换 + while (num) + { + tmp_num[js_num++] = num % base; // 注意这里,输出的数字,是小端对齐的。低位存低位 + num /= base; + } + } + + if (js_num > precision) + precision = js_num; + + field_width -= precision; + + // 靠右对齐 + if (!(flags & LEFT)) + while (field_width--) + *str++ = pad; + + if (sign) + *str++ = sign; + if (flags & SPECIAL) + if (base == 16) + { + *str++ = '0'; + *str++ = digits[33]; + } + else if (base == 8) + *str++ = digits[24]; //注意这里是英文字母O或者o + + while (js_num < precision) + { + --precision; + *str++ = '0'; + } + + while (js_num--) + *str++ = tmp_num[js_num]; + + while (field_width--) + *str++ = ' '; + + return str; } \ No newline at end of file diff --git a/kernel/printk.h b/kernel/printk.h index c568ac4f..154bd7d6 100644 --- a/kernel/printk.h +++ b/kernel/printk.h @@ -3,12 +3,14 @@ // #pragma once -#define PAD_ZERO 1 // 0填充 -#define LEFT 2 // 靠左对齐 -#define RIGHT 4 //靠右对齐 -#define PLUS 8 // 在正数前面显示加号 +#define PAD_ZERO 1 // 0填充 +#define LEFT 2 // 靠左对齐 +#define RIGHT 4 // 靠右对齐 +#define PLUS 8 // 在正数前面显示加号 #define SPACE 16 -#define SPECIAL 32 //在八进制数前面显示 '0o',在十六进制数前面显示 '0x' 或 '0X' +#define SPECIAL 32 // 在八进制数前面显示 '0o',在十六进制数前面显示 '0x' 或 '0X' +#define SMALL 64 // 十进制以上数字显示小写字母 +#define SIGN 128 // 显示符号位 #define is_digit(c) ((c) >= '0' && (c) <= '9') // 用来判断是否是数字的宏 @@ -41,4 +43,17 @@ char buf[4096]; //vsprintf()的缓冲区 * @param args 内容 * @return 最终字符串的长度 */ -int vsprintf(char *buf, const char *fmt, va_list args); \ No newline at end of file +static int vsprintf(char *buf, const char *fmt, va_list args); + + +/** + * @brief 将数字按照指定的要求转换成对应的字符串(2~36进制) + * + * @param str 要返回的字符串 + * @param num 要打印的数值 + * @param base 基数 + * @param field_width 区域宽度 + * @param precision 精度 + * @param flags 标志位 + */ +static void write_num(char* str, long long num, int base, int field_width, int precision, int flags); \ No newline at end of file