1*fb6c29d0Slogin // 2*fb6c29d0Slogin // Created by longjin on 2022/1/22. 3*fb6c29d0Slogin // 4*fb6c29d0Slogin #include <common/kprint.h> 5*fb6c29d0Slogin #include <common/printk.h> 6*fb6c29d0Slogin 7*fb6c29d0Slogin #include <common/spinlock.h> 8*fb6c29d0Slogin #include <libs/libUI/textui.h> 9*fb6c29d0Slogin #include <mm/mm.h> 10*fb6c29d0Slogin 11*fb6c29d0Slogin #include <common/math.h> 12*fb6c29d0Slogin #include <common/string.h> 13*fb6c29d0Slogin 14*fb6c29d0Slogin static spinlock_t __printk_lock = {1}; 15*fb6c29d0Slogin /** 16*fb6c29d0Slogin * @brief 将数字按照指定的要求转换成对应的字符串(2~36进制) 17*fb6c29d0Slogin * 18*fb6c29d0Slogin * @param str 要返回的字符串 19*fb6c29d0Slogin * @param num 要打印的数值 20*fb6c29d0Slogin * @param base 基数 21*fb6c29d0Slogin * @param field_width 区域宽度 22*fb6c29d0Slogin * @param precision 精度 23*fb6c29d0Slogin * @param flags 标志位 24*fb6c29d0Slogin */ 25*fb6c29d0Slogin static char *write_num(char *str, ul num, int base, int field_width, int precision, int flags); 26*fb6c29d0Slogin 27*fb6c29d0Slogin static char *write_float_point_num(char *str, double num, int field_width, int precision, int flags); 28*fb6c29d0Slogin 29*fb6c29d0Slogin static int skip_and_atoi(const char **s) 30*fb6c29d0Slogin { 31*fb6c29d0Slogin /** 32*fb6c29d0Slogin * @brief 获取连续的一段字符对应整数的值 33*fb6c29d0Slogin * @param:**s 指向 指向字符串的指针 的指针 34*fb6c29d0Slogin */ 35*fb6c29d0Slogin int ans = 0; 36*fb6c29d0Slogin while (is_digit(**s)) 37*fb6c29d0Slogin { 38*fb6c29d0Slogin ans = ans * 10 + (**s) - '0'; 39*fb6c29d0Slogin ++(*s); 40*fb6c29d0Slogin } 41*fb6c29d0Slogin return ans; 42*fb6c29d0Slogin } 43*fb6c29d0Slogin 44*fb6c29d0Slogin /** 45*fb6c29d0Slogin * @brief 将字符串按照fmt和args中的内容进行格式化,当buf_size为-1时,字符串直接保存到buf中 46*fb6c29d0Slogin * 否则将字符串前buf_size-1个字符放入,大小为buf_size的buf数组中 47*fb6c29d0Slogin * 48*fb6c29d0Slogin * @param buf 结果缓冲区 49*fb6c29d0Slogin * @param fmt 格式化字符串 50*fb6c29d0Slogin * @param args 内容 51*fb6c29d0Slogin * @param buf_size buf_size为-1时,不指定buf的大小,否则buf大小为buf_size 52*fb6c29d0Slogin * @return 最终字符串的长度 53*fb6c29d0Slogin */ 54*fb6c29d0Slogin static int __do_vsprintf(char *buf, const char *fmt, int buf_size, va_list args) 55*fb6c29d0Slogin { 56*fb6c29d0Slogin 57*fb6c29d0Slogin // 当需要输出的字符串的指针为空时,使用该字符填充目标字符串的指针 58*fb6c29d0Slogin static const char __end_zero_char = '\0'; 59*fb6c29d0Slogin 60*fb6c29d0Slogin char *str = NULL, *s = NULL, *end = NULL; 61*fb6c29d0Slogin 62*fb6c29d0Slogin str = buf; 63*fb6c29d0Slogin 64*fb6c29d0Slogin int flags; // 用来存储格式信息的bitmap 65*fb6c29d0Slogin int field_width; //区域宽度 66*fb6c29d0Slogin int precision; //精度 67*fb6c29d0Slogin int qualifier; //数据显示的类型 68*fb6c29d0Slogin int len; 69*fb6c29d0Slogin 70*fb6c29d0Slogin if (buf_size != -1) 71*fb6c29d0Slogin { 72*fb6c29d0Slogin end = buf + buf_size; 73*fb6c29d0Slogin } 74*fb6c29d0Slogin //开始解析字符串 75*fb6c29d0Slogin for (; *fmt; ++fmt) 76*fb6c29d0Slogin { 77*fb6c29d0Slogin //内容不涉及到格式化,直接输出 78*fb6c29d0Slogin if (*fmt != '%') 79*fb6c29d0Slogin { 80*fb6c29d0Slogin *str = *fmt; 81*fb6c29d0Slogin ++str; 82*fb6c29d0Slogin continue; 83*fb6c29d0Slogin } 84*fb6c29d0Slogin 85*fb6c29d0Slogin //开始格式化字符串 86*fb6c29d0Slogin 87*fb6c29d0Slogin //清空标志位和field宽度 88*fb6c29d0Slogin field_width = flags = 0; 89*fb6c29d0Slogin 90*fb6c29d0Slogin bool flag_tmp = true; 91*fb6c29d0Slogin bool flag_break = false; 92*fb6c29d0Slogin 93*fb6c29d0Slogin ++fmt; 94*fb6c29d0Slogin while (flag_tmp) 95*fb6c29d0Slogin { 96*fb6c29d0Slogin switch (*fmt) 97*fb6c29d0Slogin { 98*fb6c29d0Slogin case '\0': 99*fb6c29d0Slogin //结束解析 100*fb6c29d0Slogin flag_break = true; 101*fb6c29d0Slogin flag_tmp = false; 102*fb6c29d0Slogin break; 103*fb6c29d0Slogin 104*fb6c29d0Slogin case '-': 105*fb6c29d0Slogin // 左对齐 106*fb6c29d0Slogin flags |= LEFT; 107*fb6c29d0Slogin ++fmt; 108*fb6c29d0Slogin break; 109*fb6c29d0Slogin case '+': 110*fb6c29d0Slogin //在正数前面显示加号 111*fb6c29d0Slogin flags |= PLUS; 112*fb6c29d0Slogin ++fmt; 113*fb6c29d0Slogin break; 114*fb6c29d0Slogin case ' ': 115*fb6c29d0Slogin flags |= SPACE; 116*fb6c29d0Slogin ++fmt; 117*fb6c29d0Slogin break; 118*fb6c29d0Slogin case '#': 119*fb6c29d0Slogin //在八进制数前面显示 '0o',在十六进制数前面显示 '0x' 或 '0X' 120*fb6c29d0Slogin flags |= SPECIAL; 121*fb6c29d0Slogin ++fmt; 122*fb6c29d0Slogin break; 123*fb6c29d0Slogin case '0': 124*fb6c29d0Slogin //显示的数字之前填充‘0’来取代空格 125*fb6c29d0Slogin flags |= PAD_ZERO; 126*fb6c29d0Slogin ++fmt; 127*fb6c29d0Slogin break; 128*fb6c29d0Slogin default: 129*fb6c29d0Slogin flag_tmp = false; 130*fb6c29d0Slogin break; 131*fb6c29d0Slogin } 132*fb6c29d0Slogin } 133*fb6c29d0Slogin if (flag_break) 134*fb6c29d0Slogin break; 135*fb6c29d0Slogin 136*fb6c29d0Slogin //获取区域宽度 137*fb6c29d0Slogin field_width = -1; 138*fb6c29d0Slogin if (*fmt == '*') 139*fb6c29d0Slogin { 140*fb6c29d0Slogin field_width = va_arg(args, int); 141*fb6c29d0Slogin ++fmt; 142*fb6c29d0Slogin } 143*fb6c29d0Slogin else if (is_digit(*fmt)) 144*fb6c29d0Slogin { 145*fb6c29d0Slogin field_width = skip_and_atoi(&fmt); 146*fb6c29d0Slogin if (field_width < 0) 147*fb6c29d0Slogin { 148*fb6c29d0Slogin field_width = -field_width; 149*fb6c29d0Slogin flags |= LEFT; 150*fb6c29d0Slogin } 151*fb6c29d0Slogin } 152*fb6c29d0Slogin 153*fb6c29d0Slogin //获取小数精度 154*fb6c29d0Slogin precision = -1; 155*fb6c29d0Slogin if (*fmt == '.') 156*fb6c29d0Slogin { 157*fb6c29d0Slogin ++fmt; 158*fb6c29d0Slogin if (*fmt == '*') 159*fb6c29d0Slogin { 160*fb6c29d0Slogin precision = va_arg(args, int); 161*fb6c29d0Slogin ++fmt; 162*fb6c29d0Slogin } 163*fb6c29d0Slogin else if (is_digit(*fmt)) 164*fb6c29d0Slogin { 165*fb6c29d0Slogin precision = skip_and_atoi(&fmt); 166*fb6c29d0Slogin } 167*fb6c29d0Slogin } 168*fb6c29d0Slogin 169*fb6c29d0Slogin //获取要显示的数据的类型 170*fb6c29d0Slogin if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'Z') 171*fb6c29d0Slogin { 172*fb6c29d0Slogin qualifier = *fmt; 173*fb6c29d0Slogin ++fmt; 174*fb6c29d0Slogin } 175*fb6c29d0Slogin //为了支持lld 176*fb6c29d0Slogin if (qualifier == 'l' && *fmt == 'l', *(fmt + 1) == 'd') 177*fb6c29d0Slogin ++fmt; 178*fb6c29d0Slogin 179*fb6c29d0Slogin //转化成字符串 180*fb6c29d0Slogin long long *ip; 181*fb6c29d0Slogin switch (*fmt) 182*fb6c29d0Slogin { 183*fb6c29d0Slogin //输出 % 184*fb6c29d0Slogin case '%': 185*fb6c29d0Slogin *str++ = '%'; 186*fb6c29d0Slogin 187*fb6c29d0Slogin break; 188*fb6c29d0Slogin // 显示一个字符 189*fb6c29d0Slogin case 'c': 190*fb6c29d0Slogin //靠右对齐 191*fb6c29d0Slogin if (!(flags & LEFT)) 192*fb6c29d0Slogin { 193*fb6c29d0Slogin while (--field_width > 0) 194*fb6c29d0Slogin { 195*fb6c29d0Slogin *str = ' '; 196*fb6c29d0Slogin ++str; 197*fb6c29d0Slogin } 198*fb6c29d0Slogin } 199*fb6c29d0Slogin 200*fb6c29d0Slogin *str++ = (unsigned char)va_arg(args, int); 201*fb6c29d0Slogin 202*fb6c29d0Slogin while (--field_width > 0) 203*fb6c29d0Slogin { 204*fb6c29d0Slogin *str = ' '; 205*fb6c29d0Slogin ++str; 206*fb6c29d0Slogin } 207*fb6c29d0Slogin 208*fb6c29d0Slogin break; 209*fb6c29d0Slogin 210*fb6c29d0Slogin //显示一个字符串 211*fb6c29d0Slogin case 's': 212*fb6c29d0Slogin s = va_arg(args, char *); 213*fb6c29d0Slogin if (!s) 214*fb6c29d0Slogin s = &__end_zero_char; 215*fb6c29d0Slogin len = strlen(s); 216*fb6c29d0Slogin if (precision < 0) 217*fb6c29d0Slogin { 218*fb6c29d0Slogin //未指定精度 219*fb6c29d0Slogin precision = len; 220*fb6c29d0Slogin } 221*fb6c29d0Slogin 222*fb6c29d0Slogin else if (len > precision) 223*fb6c29d0Slogin { 224*fb6c29d0Slogin len = precision; 225*fb6c29d0Slogin } 226*fb6c29d0Slogin 227*fb6c29d0Slogin //靠右对齐 228*fb6c29d0Slogin if (!(flags & LEFT)) 229*fb6c29d0Slogin while (len < field_width--) 230*fb6c29d0Slogin { 231*fb6c29d0Slogin *str = ' '; 232*fb6c29d0Slogin ++str; 233*fb6c29d0Slogin } 234*fb6c29d0Slogin 235*fb6c29d0Slogin for (int i = 0; i < len; i++) 236*fb6c29d0Slogin { 237*fb6c29d0Slogin *str = *s; 238*fb6c29d0Slogin ++s; 239*fb6c29d0Slogin ++str; 240*fb6c29d0Slogin } 241*fb6c29d0Slogin 242*fb6c29d0Slogin while (len < field_width--) 243*fb6c29d0Slogin { 244*fb6c29d0Slogin *str = ' '; 245*fb6c29d0Slogin ++str; 246*fb6c29d0Slogin } 247*fb6c29d0Slogin 248*fb6c29d0Slogin break; 249*fb6c29d0Slogin //以八进制显示字符串 250*fb6c29d0Slogin case 'o': 251*fb6c29d0Slogin flags |= SMALL; 252*fb6c29d0Slogin case 'O': 253*fb6c29d0Slogin flags |= SPECIAL; 254*fb6c29d0Slogin if (qualifier == 'l') 255*fb6c29d0Slogin str = write_num(str, va_arg(args, long long), 8, field_width, precision, flags); 256*fb6c29d0Slogin else 257*fb6c29d0Slogin str = write_num(str, va_arg(args, int), 8, field_width, precision, flags); 258*fb6c29d0Slogin break; 259*fb6c29d0Slogin 260*fb6c29d0Slogin //打印指针指向的地址 261*fb6c29d0Slogin case 'p': 262*fb6c29d0Slogin if (field_width == 0) 263*fb6c29d0Slogin { 264*fb6c29d0Slogin field_width = 2 * sizeof(void *); 265*fb6c29d0Slogin flags |= PAD_ZERO; 266*fb6c29d0Slogin } 267*fb6c29d0Slogin 268*fb6c29d0Slogin str = write_num(str, (unsigned long)va_arg(args, void *), 16, field_width, precision, flags); 269*fb6c29d0Slogin 270*fb6c29d0Slogin break; 271*fb6c29d0Slogin 272*fb6c29d0Slogin //打印十六进制 273*fb6c29d0Slogin case 'x': 274*fb6c29d0Slogin flags |= SMALL; 275*fb6c29d0Slogin case 'X': 276*fb6c29d0Slogin // flags |= SPECIAL; 277*fb6c29d0Slogin if (qualifier == 'l') 278*fb6c29d0Slogin str = write_num(str, va_arg(args, ll), 16, field_width, precision, flags); 279*fb6c29d0Slogin else 280*fb6c29d0Slogin str = write_num(str, va_arg(args, int), 16, field_width, precision, flags); 281*fb6c29d0Slogin break; 282*fb6c29d0Slogin 283*fb6c29d0Slogin //打印十进制有符号整数 284*fb6c29d0Slogin case 'i': 285*fb6c29d0Slogin case 'd': 286*fb6c29d0Slogin 287*fb6c29d0Slogin flags |= SIGN; 288*fb6c29d0Slogin if (qualifier == 'l') 289*fb6c29d0Slogin str = write_num(str, va_arg(args, long long), 10, field_width, precision, flags); 290*fb6c29d0Slogin else 291*fb6c29d0Slogin str = write_num(str, va_arg(args, int), 10, field_width, precision, flags); 292*fb6c29d0Slogin break; 293*fb6c29d0Slogin 294*fb6c29d0Slogin //打印十进制无符号整数 295*fb6c29d0Slogin case 'u': 296*fb6c29d0Slogin if (qualifier == 'l') 297*fb6c29d0Slogin str = write_num(str, va_arg(args, unsigned long long), 10, field_width, precision, flags); 298*fb6c29d0Slogin else 299*fb6c29d0Slogin str = write_num(str, va_arg(args, unsigned int), 10, field_width, precision, flags); 300*fb6c29d0Slogin break; 301*fb6c29d0Slogin 302*fb6c29d0Slogin //输出有效字符数量到*ip对应的变量 303*fb6c29d0Slogin case 'n': 304*fb6c29d0Slogin 305*fb6c29d0Slogin if (qualifier == 'l') 306*fb6c29d0Slogin ip = va_arg(args, long long *); 307*fb6c29d0Slogin else 308*fb6c29d0Slogin ip = (ll *)va_arg(args, int *); 309*fb6c29d0Slogin 310*fb6c29d0Slogin *ip = str - buf; 311*fb6c29d0Slogin break; 312*fb6c29d0Slogin case 'f': 313*fb6c29d0Slogin // 默认精度为3 314*fb6c29d0Slogin // printk("1111\n"); 315*fb6c29d0Slogin // va_arg(args, double); 316*fb6c29d0Slogin // printk("222\n"); 317*fb6c29d0Slogin 318*fb6c29d0Slogin if (precision < 0) 319*fb6c29d0Slogin precision = 3; 320*fb6c29d0Slogin 321*fb6c29d0Slogin str = write_float_point_num(str, va_arg(args, double), field_width, precision, flags); 322*fb6c29d0Slogin 323*fb6c29d0Slogin break; 324*fb6c29d0Slogin 325*fb6c29d0Slogin //对于不识别的控制符,直接输出 326*fb6c29d0Slogin default: 327*fb6c29d0Slogin *str++ = '%'; 328*fb6c29d0Slogin if (*fmt) 329*fb6c29d0Slogin *str++ = *fmt; 330*fb6c29d0Slogin else 331*fb6c29d0Slogin --fmt; 332*fb6c29d0Slogin break; 333*fb6c29d0Slogin } 334*fb6c29d0Slogin } 335*fb6c29d0Slogin //实现vsnprintf 的功能 336*fb6c29d0Slogin if (buf_size > 0) 337*fb6c29d0Slogin { 338*fb6c29d0Slogin if (str < end) 339*fb6c29d0Slogin { 340*fb6c29d0Slogin *str = '\0'; 341*fb6c29d0Slogin } 342*fb6c29d0Slogin else 343*fb6c29d0Slogin { 344*fb6c29d0Slogin *(end-1) = '\0'; 345*fb6c29d0Slogin } 346*fb6c29d0Slogin return buf_size; 347*fb6c29d0Slogin } 348*fb6c29d0Slogin else 349*fb6c29d0Slogin { 350*fb6c29d0Slogin *str = '\0'; 351*fb6c29d0Slogin } 352*fb6c29d0Slogin 353*fb6c29d0Slogin //返回缓冲区已有字符串的长度。 354*fb6c29d0Slogin return str - buf; 355*fb6c29d0Slogin } 356*fb6c29d0Slogin 357*fb6c29d0Slogin /** 358*fb6c29d0Slogin * 将字符串按照fmt和args中的内容进行格式化,然后保存到buf中 359*fb6c29d0Slogin * @param buf 结果缓冲区 360*fb6c29d0Slogin * @param fmt 格式化字符串 361*fb6c29d0Slogin * @param args 内容 362*fb6c29d0Slogin * @return 最终字符串的长度 363*fb6c29d0Slogin */ 364*fb6c29d0Slogin int vsprintf(char *buf, const char *fmt, va_list args) 365*fb6c29d0Slogin { 366*fb6c29d0Slogin return __do_vsprintf(buf, fmt, -1, args); 367*fb6c29d0Slogin } 368*fb6c29d0Slogin 369*fb6c29d0Slogin /** 370*fb6c29d0Slogin * @brief 将字符串按照fmt和args中的内容进行格式化,截取字符串前buf_size-1,保存到buf中 371*fb6c29d0Slogin * 372*fb6c29d0Slogin * @param buf 结果缓冲区,大小为buf_size 373*fb6c29d0Slogin * @param fmt 格式化字符串 374*fb6c29d0Slogin * @param buf_size 缓冲区长度 375*fb6c29d0Slogin * @param args 内容 376*fb6c29d0Slogin * @return 最终字符串的长度 377*fb6c29d0Slogin */ 378*fb6c29d0Slogin int vsnprintf(char *buf, const char *fmt, int buf_size, va_list args) 379*fb6c29d0Slogin { 380*fb6c29d0Slogin return __do_vsprintf(buf, fmt, buf_size, args); 381*fb6c29d0Slogin } 382*fb6c29d0Slogin 383*fb6c29d0Slogin static char *write_num(char *str, ul num, int base, int field_width, int precision, int flags) 384*fb6c29d0Slogin { 385*fb6c29d0Slogin /** 386*fb6c29d0Slogin * @brief 将数字按照指定的要求转换成对应的字符串 387*fb6c29d0Slogin * 388*fb6c29d0Slogin * @param str 要返回的字符串 389*fb6c29d0Slogin * @param num 要打印的数值 390*fb6c29d0Slogin * @param base 基数 391*fb6c29d0Slogin * @param field_width 区域宽度 392*fb6c29d0Slogin * @param precision 精度 393*fb6c29d0Slogin * @param flags 标志位 394*fb6c29d0Slogin */ 395*fb6c29d0Slogin 396*fb6c29d0Slogin // 首先判断是否支持该进制 397*fb6c29d0Slogin if (base < 2 || base > 36) 398*fb6c29d0Slogin return 0; 399*fb6c29d0Slogin char pad, sign, tmp_num[100]; 400*fb6c29d0Slogin 401*fb6c29d0Slogin const char *digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 402*fb6c29d0Slogin // 显示小写字母 403*fb6c29d0Slogin if (flags & SMALL) 404*fb6c29d0Slogin digits = "0123456789abcdefghijklmnopqrstuvwxyz"; 405*fb6c29d0Slogin 406*fb6c29d0Slogin if (flags & LEFT) 407*fb6c29d0Slogin flags &= ~PAD_ZERO; 408*fb6c29d0Slogin // 设置填充元素 409*fb6c29d0Slogin pad = (flags & PAD_ZERO) ? '0' : ' '; 410*fb6c29d0Slogin 411*fb6c29d0Slogin sign = 0; 412*fb6c29d0Slogin 413*fb6c29d0Slogin if (flags & SIGN) 414*fb6c29d0Slogin { 415*fb6c29d0Slogin int64_t signed_num = (int64_t)num; 416*fb6c29d0Slogin if (signed_num < 0) 417*fb6c29d0Slogin { 418*fb6c29d0Slogin sign = '-'; 419*fb6c29d0Slogin num = -signed_num; 420*fb6c29d0Slogin } 421*fb6c29d0Slogin else 422*fb6c29d0Slogin num = signed_num; 423*fb6c29d0Slogin } 424*fb6c29d0Slogin else 425*fb6c29d0Slogin { 426*fb6c29d0Slogin // 设置符号 427*fb6c29d0Slogin sign = (flags & PLUS) ? '+' : ((flags & SPACE) ? ' ' : 0); 428*fb6c29d0Slogin } 429*fb6c29d0Slogin 430*fb6c29d0Slogin // sign占用了一个宽度 431*fb6c29d0Slogin if (sign) 432*fb6c29d0Slogin --field_width; 433*fb6c29d0Slogin 434*fb6c29d0Slogin if (flags & SPECIAL) 435*fb6c29d0Slogin if (base == 16) // 0x占用2个位置 436*fb6c29d0Slogin field_width -= 2; 437*fb6c29d0Slogin else if (base == 8) // O占用一个位置 438*fb6c29d0Slogin --field_width; 439*fb6c29d0Slogin 440*fb6c29d0Slogin int js_num = 0; // 临时数字字符串tmp_num的长度 441*fb6c29d0Slogin 442*fb6c29d0Slogin if (num == 0) 443*fb6c29d0Slogin tmp_num[js_num++] = '0'; 444*fb6c29d0Slogin else 445*fb6c29d0Slogin { 446*fb6c29d0Slogin num = ABS(num); 447*fb6c29d0Slogin //进制转换 448*fb6c29d0Slogin while (num > 0) 449*fb6c29d0Slogin { 450*fb6c29d0Slogin tmp_num[js_num++] = digits[num % base]; // 注意这里,输出的数字,是小端对齐的。低位存低位 451*fb6c29d0Slogin num /= base; 452*fb6c29d0Slogin } 453*fb6c29d0Slogin } 454*fb6c29d0Slogin 455*fb6c29d0Slogin if (js_num > precision) 456*fb6c29d0Slogin precision = js_num; 457*fb6c29d0Slogin 458*fb6c29d0Slogin field_width -= precision; 459*fb6c29d0Slogin 460*fb6c29d0Slogin // 靠右对齐 461*fb6c29d0Slogin if (!(flags & (LEFT + PAD_ZERO))) 462*fb6c29d0Slogin while (field_width-- > 0) 463*fb6c29d0Slogin *str++ = ' '; 464*fb6c29d0Slogin 465*fb6c29d0Slogin if (sign) 466*fb6c29d0Slogin *str++ = sign; 467*fb6c29d0Slogin if (flags & SPECIAL) 468*fb6c29d0Slogin if (base == 16) 469*fb6c29d0Slogin { 470*fb6c29d0Slogin *str++ = '0'; 471*fb6c29d0Slogin *str++ = digits[33]; 472*fb6c29d0Slogin } 473*fb6c29d0Slogin else if (base == 8) 474*fb6c29d0Slogin *str++ = digits[24]; //注意这里是英文字母O或者o 475*fb6c29d0Slogin if (!(flags & LEFT)) 476*fb6c29d0Slogin while (field_width-- > 0) 477*fb6c29d0Slogin *str++ = pad; 478*fb6c29d0Slogin while (js_num < precision) 479*fb6c29d0Slogin { 480*fb6c29d0Slogin --precision; 481*fb6c29d0Slogin *str++ = '0'; 482*fb6c29d0Slogin } 483*fb6c29d0Slogin 484*fb6c29d0Slogin while (js_num-- > 0) 485*fb6c29d0Slogin *str++ = tmp_num[js_num]; 486*fb6c29d0Slogin 487*fb6c29d0Slogin while (field_width-- > 0) 488*fb6c29d0Slogin *str++ = ' '; 489*fb6c29d0Slogin 490*fb6c29d0Slogin return str; 491*fb6c29d0Slogin } 492*fb6c29d0Slogin 493*fb6c29d0Slogin static char *write_float_point_num(char *str, double num, int field_width, int precision, int flags) 494*fb6c29d0Slogin { 495*fb6c29d0Slogin /** 496*fb6c29d0Slogin * @brief 将浮点数按照指定的要求转换成对应的字符串 497*fb6c29d0Slogin * 498*fb6c29d0Slogin * @param str 要返回的字符串 499*fb6c29d0Slogin * @param num 要打印的数值 500*fb6c29d0Slogin * @param field_width 区域宽度 501*fb6c29d0Slogin * @param precision 精度 502*fb6c29d0Slogin * @param flags 标志位 503*fb6c29d0Slogin */ 504*fb6c29d0Slogin 505*fb6c29d0Slogin char pad, sign, tmp_num_z[100], tmp_num_d[350]; 506*fb6c29d0Slogin 507*fb6c29d0Slogin const char *digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; 508*fb6c29d0Slogin // 显示小写字母 509*fb6c29d0Slogin if (flags & SMALL) 510*fb6c29d0Slogin digits = "0123456789abcdefghijklmnopqrstuvwxyz"; 511*fb6c29d0Slogin 512*fb6c29d0Slogin // 设置填充元素 513*fb6c29d0Slogin pad = (flags & PAD_ZERO) ? '0' : ' '; 514*fb6c29d0Slogin sign = 0; 515*fb6c29d0Slogin if (flags & SIGN && num < 0) 516*fb6c29d0Slogin { 517*fb6c29d0Slogin sign = '-'; 518*fb6c29d0Slogin num = -num; 519*fb6c29d0Slogin } 520*fb6c29d0Slogin else 521*fb6c29d0Slogin { 522*fb6c29d0Slogin // 设置符号 523*fb6c29d0Slogin sign = (flags & PLUS) ? '+' : ((flags & SPACE) ? ' ' : 0); 524*fb6c29d0Slogin } 525*fb6c29d0Slogin 526*fb6c29d0Slogin // sign占用了一个宽度 527*fb6c29d0Slogin if (sign) 528*fb6c29d0Slogin --field_width; 529*fb6c29d0Slogin 530*fb6c29d0Slogin int js_num_z = 0, js_num_d = 0; // 临时数字字符串tmp_num_z tmp_num_d的长度 531*fb6c29d0Slogin uint64_t num_z = (uint64_t)(num); // 获取整数部分 532*fb6c29d0Slogin uint64_t num_decimal = (uint64_t)(round(1.0 * (num - num_z) * pow(10, precision))); // 获取小数部分 533*fb6c29d0Slogin 534*fb6c29d0Slogin if (num == 0 || num_z == 0) 535*fb6c29d0Slogin tmp_num_z[js_num_z++] = '0'; 536*fb6c29d0Slogin else 537*fb6c29d0Slogin { 538*fb6c29d0Slogin //存储整数部分 539*fb6c29d0Slogin while (num_z > 0) 540*fb6c29d0Slogin { 541*fb6c29d0Slogin tmp_num_z[js_num_z++] = digits[num_z % 10]; // 注意这里,输出的数字,是小端对齐的。低位存低位 542*fb6c29d0Slogin num_z /= 10; 543*fb6c29d0Slogin } 544*fb6c29d0Slogin } 545*fb6c29d0Slogin 546*fb6c29d0Slogin while (num_decimal > 0) 547*fb6c29d0Slogin { 548*fb6c29d0Slogin tmp_num_d[js_num_d++] = digits[num_decimal % 10]; 549*fb6c29d0Slogin num_decimal /= 10; 550*fb6c29d0Slogin } 551*fb6c29d0Slogin 552*fb6c29d0Slogin field_width -= (precision + 1 + js_num_z); 553*fb6c29d0Slogin 554*fb6c29d0Slogin // 靠右对齐 555*fb6c29d0Slogin if (!(flags & LEFT)) 556*fb6c29d0Slogin while (field_width-- > 0) 557*fb6c29d0Slogin *str++ = pad; 558*fb6c29d0Slogin 559*fb6c29d0Slogin if (sign) 560*fb6c29d0Slogin *str++ = sign; 561*fb6c29d0Slogin 562*fb6c29d0Slogin // 输出整数部分 563*fb6c29d0Slogin while (js_num_z > 0) 564*fb6c29d0Slogin { 565*fb6c29d0Slogin *str++ = tmp_num_z[js_num_z - 1]; 566*fb6c29d0Slogin --js_num_z; 567*fb6c29d0Slogin } 568*fb6c29d0Slogin *str++ = '.'; 569*fb6c29d0Slogin 570*fb6c29d0Slogin // 输出小数部分 571*fb6c29d0Slogin int total_dec_count = js_num_d; 572*fb6c29d0Slogin for (int i = 0; i < precision && js_num_d-- > 0; ++i) 573*fb6c29d0Slogin *str++ = tmp_num_d[js_num_d]; 574*fb6c29d0Slogin 575*fb6c29d0Slogin while (total_dec_count < precision) 576*fb6c29d0Slogin { 577*fb6c29d0Slogin ++total_dec_count; 578*fb6c29d0Slogin *str++ = '0'; 579*fb6c29d0Slogin } 580*fb6c29d0Slogin 581*fb6c29d0Slogin while (field_width-- > 0) 582*fb6c29d0Slogin *str++ = ' '; 583*fb6c29d0Slogin 584*fb6c29d0Slogin return str; 585*fb6c29d0Slogin } 586*fb6c29d0Slogin 587*fb6c29d0Slogin /** 588*fb6c29d0Slogin * @brief 格式化打印字符串 589*fb6c29d0Slogin * 590*fb6c29d0Slogin * @param FRcolor 前景色 591*fb6c29d0Slogin * @param BKcolor 背景色 592*fb6c29d0Slogin * @param ... 格式化字符串 593*fb6c29d0Slogin */ 594*fb6c29d0Slogin int printk_color(unsigned int FRcolor, unsigned int BKcolor, const char *fmt, ...) 595*fb6c29d0Slogin { 596*fb6c29d0Slogin uint64_t rflags; 597*fb6c29d0Slogin spin_lock_irqsave(&__printk_lock, rflags); 598*fb6c29d0Slogin va_list args; 599*fb6c29d0Slogin va_start(args, fmt); 600*fb6c29d0Slogin char buf[4096]; // vsprintf()的缓冲区 601*fb6c29d0Slogin int len = vsprintf(buf, fmt, args); 602*fb6c29d0Slogin 603*fb6c29d0Slogin va_end(args); 604*fb6c29d0Slogin unsigned char current; 605*fb6c29d0Slogin 606*fb6c29d0Slogin int i; // 总共输出的字符数 607*fb6c29d0Slogin for (i = 0; i < len; ++i) 608*fb6c29d0Slogin { 609*fb6c29d0Slogin current = *(buf + i); 610*fb6c29d0Slogin // 输出 611*fb6c29d0Slogin textui_putchar(current, FRcolor, BKcolor); 612*fb6c29d0Slogin } 613*fb6c29d0Slogin spin_unlock_irqrestore(&__printk_lock, rflags); 614*fb6c29d0Slogin return i; 615*fb6c29d0Slogin } 616*fb6c29d0Slogin 617*fb6c29d0Slogin int sprintk(char *buf, const char *fmt, ...) 618*fb6c29d0Slogin { 619*fb6c29d0Slogin int count = 0; 620*fb6c29d0Slogin va_list args; 621*fb6c29d0Slogin 622*fb6c29d0Slogin va_start(args, fmt); 623*fb6c29d0Slogin count = vsprintf(buf, fmt, args); 624*fb6c29d0Slogin va_end(args); 625*fb6c29d0Slogin 626*fb6c29d0Slogin return count; 627*fb6c29d0Slogin } 628