DragonOS/kernel/printk.c

171 lines
3.9 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// Created by longjin on 2022/1/22.
//
#include "printk.h"
int skip_and_atoi(const char **s)
{
/**
* @brief 获取连续的一段字符对应整数的值
* @param:**s 指向 指向字符串的指针 的指针
*/
int ans = 0;
while (is_digit(**s))
{
ans = ans * 10 + (**s) - '0';
++(*s);
}
return ans;
}
int vsprintf(char *buf, const char *fmt, va_list args)
{
/**
* 将字符串按照fmt和args中的内容进行格式化然后保存到buf中
* @param buf 结果缓冲区
* @param fmt 格式化字符串
* @param args 内容
* @return 最终字符串的长度
*/
char *str, *s;
str = buf;
int flags; // 用来存储格式信息的bitmap
int field_width; //区域宽度
int precision; //精度
int qualifier; //数据显示的类型
int len;
//开始解析字符串
for (; *fmt; ++fmt)
{
//内容不涉及到格式化,直接输出
if (*fmt != '%')
{
*str = *fmt;
++str;
}
//开始格式化字符串
//清空标志位和field宽度
field_width = flags = 0;
++fmt;
bool flag_tmp = true;
bool flag_break = false;
while (flag_tmp)
{
switch (*fmt)
{
case '\0':
//结束解析
flag_break = true;
flag_tmp = false;
break;
case '%':
//输出 %
*str = '%';
++str;
++fmt;
flag_break = true;
break;
case '-':
// 左对齐
flags |= LEFT;
++fmt;
break;
case '+':
//在正数前面显示加号
flags |= PLUS;
++fmt;
break;
case ' ':
flags |= SPACE;
++fmt;
break;
case '#':
//在八进制数前面显示 '0o',在十六进制数前面显示 '0x' 或 '0X'
flags |= SPECIAL;
++fmt;
break;
case '0':
//显示的数字之前填充0来取代空格
flags |= PAD_ZERO;
++fmt;
break;
default:
flag_tmp = false;
break;
}
}
if (flag_break)
break;
//获取区域宽度
if (*fmt == '*')
{
field_width = va_arg(args, int);
++fmt;
}
else if (is_digit(*fmt))
field_width = skip_and_atoi(&fmt);
//获取小数精度
if (*fmt == '.')
{
++fmt;
if (*fmt == '*')
{
precision = va_arg(args, int);
++fmt;
}
else if is_digit (*fmt)
{
precision = skip_and_atoi(&fmt);
}
}
//获取要显示的数据的类型
if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L' || *fmt == 'Z')
{
qualifier = *fmt;
++fmt;
}
//转化成字符串
switch (*fmt)
{
// 显示一个字符
case 'c':
//靠右对齐
if (!(flags & LEFT))
{
while (--field_width)
{
*str = ' ';
++str;
}
}
else //靠左对齐
{
*str = (char)va_arg(args, int);
++str;
--field_width;
}
while (--field_width)
{
*str = ' ';
++str;
}
break;
default:
break;
}
}
}