🆕 printk.c, 在vsprintf中部分完成了解析字符串的工作

This commit is contained in:
fslongjin
2022-01-22 15:55:34 +08:00
parent 8ab4d5b98a
commit df7b3a3716
3 changed files with 212 additions and 0 deletions

7
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,7 @@
{
"files.associations": {
"stdlib.h": "c",
"stdbool.h": "c",
"printk.h": "c"
}
}

171
kernel/printk.c Normal file
View File

@ -0,0 +1,171 @@
//
// 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;
}
}
}

34
kernel/printk.h Normal file
View File

@ -0,0 +1,34 @@
//
// Created by longjin on 2022/1/21.
//
#pragma once
#define PAD_ZERO 1 // 0填充
#define LEFT 2 // 靠左对齐
#define RIGHT 4 //靠右对齐
#define PLUS 8 // 在正数前面显示加号
#define SPACE 16
#define SPECIAL 32 //在八进制数前面显示 '0o',在十六进制数前面显示 '0x' 或 '0X'
#define is_digit(c) ((c) >= '0' && (c) <= '9') // 用来判断是否是数字的宏
#include "font.h"
#include "glib.h"
#include <stdarg.h>
struct screen_info
{
int width, height; //屏幕大小
int x, y; //光标位置
int char_size_x, char_size_y;
unsigned int *FB_address; //帧缓冲区首地址
unsigned long FB_length; // 帧缓冲区长度
} pos;
extern unsigned char font_ascii[256][16]; //导出ascii字体的bitmap8*16大小
char buf[4096]; //vsprintf()的缓冲区