xref: /DragonOS/kernel/src/libs/printk.c (revision fb6c29d01d4cf92368efec08c01e419c2a941f7d) !
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