浏览代码

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

fslongjin 3 年之前
父节点
当前提交
df7b3a3716
共有 3 个文件被更改,包括 212 次插入0 次删除
  1. 7 0
      .vscode/settings.json
  2. 171 0
      kernel/printk.c
  3. 34 0
      kernel/printk.h

+ 7 - 0
.vscode/settings.json

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

+ 171 - 0
kernel/printk.c

@@ -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 - 0
kernel/printk.h

@@ -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字体的bitmap(8*16大小)
+
+char buf[4096]; //vsprintf()的缓冲区