From d931f612f809e56af3a07f78367b8b7bdd615f25 Mon Sep 17 00:00:00 2001 From: pointer-to-bios Date: Thu, 1 Feb 2024 01:40:51 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=86=85=E6=A0=B8=E6=97=A5?= =?UTF-8?q?=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Makefile | 1 - src/kernel/clock/time.rs | 6 +- src/kernel/klog.rs | 152 ++++++++++++++++++++-------------- src/kernel/main.rs | 20 +++-- src/kernel/tty/font.c | 2 +- src/kernel/tty/mod.rs | 45 ++++++++++ src/kernel/tty/tty.rs | 136 +++++++++--------------------- src/libk/mod.rs | 1 + src/libk/string/format/mod.rs | 38 +++++++++ src/libk/string/mod.rs | 1 + 10 files changed, 233 insertions(+), 169 deletions(-) create mode 100644 src/libk/string/format/mod.rs create mode 100644 src/libk/string/mod.rs diff --git a/src/Makefile b/src/Makefile index 6ea2cf8..3957d4b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -46,7 +46,6 @@ metaverse.elf: kernel libk rust metaverse.lds @echo -e "\e[1;33mld\e[0m \e[1;32m$@\e[0m \e[34m<--\e[0m \e[32m${SUBOBJS}\e[0m" @ld -T metaverse.lds -Map=metaverse.map -unresolved-symbols=ignore-all -o $@ ${SUBOBJS} ${RUST_LIBS} \ 2>&1 | "${SOURCE}/colorize" "warning:=yellow" "error:=red" "ld=lyellow" - @strip $@ .PHONY: kernel libk all clear postproc rust diff --git a/src/kernel/clock/time.rs b/src/kernel/clock/time.rs index 7f56363..29f86bd 100644 --- a/src/kernel/clock/time.rs +++ b/src/kernel/clock/time.rs @@ -1,6 +1,8 @@ use core::{cmp::Ordering, ops::Sub, time::Duration}; -use alloc::{format, string::ToString}; +use alloc::string::ToString; + +use crate::format; extern "C" { fn system_time_get() -> usize; @@ -96,7 +98,7 @@ impl ToString for SystemTime { let milisec = second % second_dur; second /= second_dur; format!( - "[{:02}-{:02}-{:02} {:02}:{:02}:{:02}.{:03}]", + "[ {}-{}-{} {}:{}:{}.{} ]", year, month, day, hour, minute, second, milisec ) } diff --git a/src/kernel/klog.rs b/src/kernel/klog.rs index 3e157fb..8cc5416 100644 --- a/src/kernel/klog.rs +++ b/src/kernel/klog.rs @@ -1,6 +1,6 @@ use alloc::string::ToString; -use alloc::{format, vec::Vec}; use alloc::vec; +use alloc::vec::Vec; use super::{ clock::time::SystemTime, @@ -40,125 +40,157 @@ impl KernelLogger { pub fn fatal(&mut self, msg: Message) { let msg = MessageBuilder::new() - .message("Fatal: ".to_string()) + .message("Fatal: ") .foreground_color(Color(0xee, 0xa, 0xa)) - .append(MessageBuilder::from_message(&msg)) + .append(MessageBuilder::from_message(msg)) .build(); self.fatal_queue.push((SystemTime::now(), msg)); } pub fn error(&mut self, msg: Message) { let msg = MessageBuilder::new() - .message("Error: ".to_string()) + .message("Error: ") .foreground_color(Color(0xaa, 0x22, 0x22)) - .append(MessageBuilder::from_message(&msg)) + .append(MessageBuilder::from_message(msg)) .build(); self.error_queue.push((SystemTime::now(), msg)); } pub fn warning(&mut self, msg: Message) { let msg = MessageBuilder::new() - .message("Warning: ".to_string()) + .message("Warning: ") .foreground_color(Color(0xaa, 0xa, 0xaa)) - .append(MessageBuilder::from_message(&msg)) + .append(MessageBuilder::from_message(msg)) .build(); self.warning_queue.push((SystemTime::now(), msg)); } pub fn info(&mut self, msg: Message) { let msg = MessageBuilder::new() - .message("Info: ".to_string()) + .message("Info: ") .foreground_color(Color(0xa, 0xee, 0xa)) - .append(MessageBuilder::from_message(&msg)) + .append(MessageBuilder::from_message(msg)) .build(); self.info_queue.push((SystemTime::now(), msg)); } pub fn debug(&mut self, msg: Message) { let msg = MessageBuilder::new() - .message("Debug: ".to_string()) + .message("Debug: ") .foreground_color(Color(0xee, 0xee, 0xee)) - .append(MessageBuilder::from_message(&msg)) + .append(MessageBuilder::from_message(msg)) .build(); self.debug_queue.push((SystemTime::now(), msg)); } pub fn trace(&mut self, msg: Message) { let msg = MessageBuilder::new() - .message("Trace: ".to_string()) + .message("Trace: ") .foreground_color(Color(0xee, 0xee, 0xee)) - .append(MessageBuilder::from_message(&msg)) + .append(MessageBuilder::from_message(msg)) .build(); self.trace_queue.push((SystemTime::now(), msg)); } pub fn iter(&self, level: LoggerLevel) -> LogIterator { let mut logs = vec![]; - if level == LoggerLevel::Fatal { - logs.push(&self.fatal_queue); - } - if level == LoggerLevel::Fatal || level == LoggerLevel::Error { - logs.push(&self.error_queue); - } - if level == LoggerLevel::Fatal - || level == LoggerLevel::Error - || level == LoggerLevel::Warning - { - logs.push(&self.warning_queue); - } - if level == LoggerLevel::Fatal - || level == LoggerLevel::Error - || level == LoggerLevel::Warning - || level == LoggerLevel::Info - { - logs.push(&self.info_queue); - } - if level == LoggerLevel::Fatal - || level == LoggerLevel::Error - || level == LoggerLevel::Warning - || level == LoggerLevel::Info - || level == LoggerLevel::Debug - { - logs.push(&self.debug_queue); - } - if level == LoggerLevel::Fatal - || level == LoggerLevel::Error - || level == LoggerLevel::Warning - || level == LoggerLevel::Info - || level == LoggerLevel::Debug - || level == LoggerLevel::Trace - { - logs.push(&self.trace_queue); + match level { + LoggerLevel::Fatal => { + logs.push(&self.fatal_queue); + } + LoggerLevel::Error => { + logs.push(&self.fatal_queue); + logs.push(&self.error_queue); + } + LoggerLevel::Warning => { + logs.push(&self.fatal_queue); + logs.push(&self.error_queue); + logs.push(&self.warning_queue); + } + LoggerLevel::Info => { + logs.push(&self.fatal_queue); + logs.push(&self.error_queue); + logs.push(&self.warning_queue); + logs.push(&self.info_queue); + } + LoggerLevel::Debug => { + logs.push(&self.fatal_queue); + logs.push(&self.error_queue); + logs.push(&self.warning_queue); + logs.push(&self.info_queue); + logs.push(&self.debug_queue); + } + LoggerLevel::Trace => { + logs.push(&self.fatal_queue); + logs.push(&self.error_queue); + logs.push(&self.warning_queue); + logs.push(&self.info_queue); + logs.push(&self.debug_queue); + logs.push(&self.trace_queue); + } } let mut res = vec![]; - while let Some(msg) = { - logs.iter_mut() - .filter_map(|&mut l| l.first().cloned()) - .min_by_key(|&(syst, _)| syst) - } { - res.push(msg); + let mut indeces = Vec::new(); + for _ in 0..logs.len() { + indeces.push(0usize); + } + let all_end = |indeces: &Vec, logs: &Vec<&Vec<(SystemTime, Message)>>| { + for i in 0..indeces.len() { + if indeces[i] < logs.len() { + return false; + } + } + return true; + }; + while !all_end(&indeces, &logs) { + let mut min_ind = None; + let mut min = None; + for i in 0..indeces.len() { + if indeces[i] >= logs[i].len() { + continue; + } + if let Some(minx) = min.as_mut() { + if logs[i][indeces[i]].0 < *minx { + *minx = logs[i][indeces[i]].0; + min_ind = Some(i); + } + } else { + min = Some(logs[i][indeces[i]].0); + min_ind = Some(i); + } + } + if let Some(mini) = min_ind { + res.push(&logs[mini][indeces[mini]]); + indeces[mini] += 1; + } else { + break; + } } LogIterator { logs: res } } } -pub struct LogIterator { - logs: Vec<(SystemTime, Message)>, +pub struct LogIterator<'a> { + logs: Vec<&'a (SystemTime, Message)>, } -impl Iterator for LogIterator { +impl<'a> Iterator for LogIterator<'a> { type Item = Message; fn next(&mut self) -> Option { - if let Some((time, msg)) = self.logs.first() { + let res = if let Some((time, msg)) = self.logs.first() { Some( MessageBuilder::new() - .message(format!("{}", time.to_string())) - .append(MessageBuilder::from_message(msg)) + .message(&time.to_string()) + .append(MessageBuilder::from_message(msg.clone())) .build(), ) } else { None + }; + if let Some(_) = res { + self.logs.remove(0); } + res } } diff --git a/src/kernel/main.rs b/src/kernel/main.rs index 5d0373a..aa74b88 100644 --- a/src/kernel/main.rs +++ b/src/kernel/main.rs @@ -1,17 +1,21 @@ +use crate::message; + use super::{ klog::{KernelLogger, LoggerLevel}, - tty::tty::{Color, ColorPair, Message, Tty}, + tty::tty::{BuilderFunctions::*, Color, Tty}, }; #[no_mangle] -extern "C" fn kmain_rust() { - let mut logger = KernelLogger::new(); - logger.info(Message::from(format!( - "Hello, {:?}Metaverse{:?}!", - ColorPair::color(Color(0xa, 0xee, 0xa), Color(0, 0, 0)), - ColorPair::Reset - ))); +extern "C" fn kmain_rust() -> ! { let tty = Tty::from_id(0).unwrap(); + tty.enable(); + let mut logger = KernelLogger::new(); + logger.info(message!( + Msg("Hello, "), + Msg("Metaverse"), + FgColor(Color(0xa, 0xee, 0xa)), + Msg("!\n") + )); for msg in logger.iter(LoggerLevel::Info) { tty.print(msg); } diff --git a/src/kernel/tty/font.c b/src/kernel/tty/font.c index 684fc32..57d78f5 100644 --- a/src/kernel/tty/font.c +++ b/src/kernel/tty/font.c @@ -405,7 +405,7 @@ u64 font[256][64] = { 0b00000000, 0b00011000, /// 0b00101000, - 0b01001000, + 0b00001000, 0b00001000, 0b00001000, 0b00001000, diff --git a/src/kernel/tty/mod.rs b/src/kernel/tty/mod.rs index cd8fd47..ed058fa 100644 --- a/src/kernel/tty/mod.rs +++ b/src/kernel/tty/mod.rs @@ -1 +1,46 @@ pub mod tty; + +#[macro_export] +macro_rules! message_msg { + () => {}; + ( $builder : expr, $e : expr) => { + $builder.message_mut($e); + }; +} + +#[macro_export] +macro_rules! message_fgc { + () => {}; + ( $builder : expr, $e : expr) => { + $builder.foreground_color_mut($e); + }; +} + +#[macro_export] +macro_rules! message_bgc { + () => {}; + ( $builder : expr, $e : expr ) => { + $builder.background_color_mut($e); + }; +} + +#[macro_export] +macro_rules! message { + ( $( $e : expr ),* ) => {{ + use crate::{ + kernel::tty::tty::{MessageBuilder, BuilderFunctions}, + message_msg, message_fgc, message_bgc + }; + let mut tmp_builder = MessageBuilder::new(); + $( + if let BuilderFunctions::Msg(e) = $e { + message_msg!(tmp_builder, e); + } else if let BuilderFunctions::FgColor(c) = $e { + message_fgc!(tmp_builder, c); + } else if let BuilderFunctions::BgColor(c) = $e { + message_bgc!(tmp_builder, c); + } + )* + tmp_builder.build() + }}; +} diff --git a/src/kernel/tty/tty.rs b/src/kernel/tty/tty.rs index 5cb1011..38922ee 100644 --- a/src/kernel/tty/tty.rs +++ b/src/kernel/tty/tty.rs @@ -1,7 +1,6 @@ use core::ptr::null_mut; use alloc::{ - format, string::{String, ToString}, vec, vec::Vec, @@ -145,38 +144,6 @@ impl Tty { #[derive(Clone, Copy)] pub struct Color(pub u8, pub u8, pub u8); -impl ToString for Color { - fn to_string(&self) -> String { - format!("{:02x}{:02x}{:02x}", self.0, self.1, self.2) - } -} - -pub enum ColorPair { - Reset, - Color { fore: Color, back: Color }, -} - -impl ColorPair { - pub fn reset() -> Self { - ColorPair::Reset - } - - pub fn color(fore: Color, back: Color) -> Self { - ColorPair::Color { fore, back } - } -} - -impl ToString for ColorPair { - fn to_string(&self) -> String { - match self { - ColorPair::Reset => format!("\x1b{{}}"), - ColorPair::Color { fore, back } => { - format!("\x1b{{{}{}}}", fore.to_string(), back.to_string()) - } - } - } -} - impl From for u32 { fn from(value: Color) -> Self { let res = (value.0 as u32) << 16 | (value.1 as u32) << 8 | (value.2 as u32); @@ -196,71 +163,46 @@ pub struct MessageSection { bgcolor: Color, } +/// ## Message +/// +/// 用`MessageBuilder`构造一个`Message`对象 #[derive(Clone)] pub struct Message(Vec); -impl From for Message { - fn from(value: String) -> Self { - let mut res = MessageBuilder::new(); - let mut msg = String::new(); - let mut color = ColorPair::Reset; - let mut coloring = false; - - let mut colorp_str = String::new(); - - for c in value.as_bytes() { - if *c as char == '\x1b' { - coloring = true; - res.message_mut(msg.clone()); - msg.clear(); - if let ColorPair::Color { fore, back } = color { - res.foreground_color_mut(fore); - res.background_color_mut(back); - } - continue; - } - if coloring { - if *c as char == '{' { - colorp_str.clear(); - } else if *c as char == '}' { - if colorp_str.is_empty() { - color = ColorPair::Reset; - } else { - let bts = colorp_str.as_bytes(); - let r = bts[0] << 4 + bts[1]; - let g = bts[2] << 4 + bts[3]; - let b = bts[4] << 4 + bts[5]; - let fore = Color(r, g, b); - let r = bts[6] << 4 + bts[7]; - let g = bts[8] << 4 + bts[9]; - let b = bts[10] << 4 + bts[11]; - let back = Color(r, g, b); - color = ColorPair::Color { fore, back }; - } - coloring = false; - } else { - colorp_str.push(*c as char); - } - continue; - } - msg.push(*c as char); - } - if !msg.is_empty() { - res.message_mut(msg.clone()); - msg.clear(); - if let ColorPair::Color { fore, back } = color { - res.foreground_color_mut(fore); - res.background_color_mut(back); - } - } - res.build() - } -} - +/// ## MessageBuilder +/// +/// 使用链式调用模式构造一个消息. +/// +/// 一个`Message`包含多个`MessageSection`,每个`MessageSection`以`message()`调用开始, +/// `message()`调用后可接0个或多个属性设置。 +/// +/// ```rust +/// MessageBuilder::new() +/// .message("Hello, ") +/// .message("Metaverse").foreground_color(Color(0xa, 0xee, 0xa)) +/// .message("!\n") +/// .build(); +/// ``` +/// +/// 对于特殊情况可以使用非链式调用: +/// ```rust +/// let mut msg = MessageBuilder::new(); +/// msg.message_mut("Hello, "); +/// msg.message_mut("Metaverse"); +/// msg.foreground_color(Color(0xa, 0xee, 0xa)); +/// msg.message_mut("!\n"); +/// let msg = msg.build(); +/// ``` pub struct MessageBuilder { msg: Message, } +pub enum BuilderFunctions<'a> { + Msg(&'a str), + FgColor(Color), + BgColor(Color), +} + impl MessageBuilder { pub fn new() -> Self { Self { @@ -268,22 +210,22 @@ impl MessageBuilder { } } - pub fn from_message(msg: &Message) -> Self { - Self { msg: msg.clone() } + pub fn from_message(msg: Message) -> Self { + Self { msg } } - pub fn message(mut self, msg: String) -> Self { + pub fn message(mut self, msg: &str) -> Self { self.msg.0.push(MessageSection { - msg, + msg: msg.to_string(), fgcolor: Color(0xee, 0xee, 0xee), bgcolor: Color(0, 0, 0), }); self } - pub fn message_mut(&mut self, msg: String) { + pub fn message_mut(&mut self, msg: &str) { self.msg.0.push(MessageSection { - msg, + msg: msg.to_string(), fgcolor: Color(0xee, 0xee, 0xee), bgcolor: Color(0, 0, 0), }); diff --git a/src/libk/mod.rs b/src/libk/mod.rs index e69de29..d245b85 100644 --- a/src/libk/mod.rs +++ b/src/libk/mod.rs @@ -0,0 +1 @@ +pub mod string; diff --git a/src/libk/string/format/mod.rs b/src/libk/string/format/mod.rs new file mode 100644 index 0000000..8d63056 --- /dev/null +++ b/src/libk/string/format/mod.rs @@ -0,0 +1,38 @@ +use alloc::string::{String, ToString}; + +#[macro_export] +macro_rules! format { + ( $s : expr, $( $e : expr ),* ) => {{ + use crate::libk::string::format::Format; + let mut res = $s.to_string(); + $( + res.format($e); + )* + res + }}; + () => {}; +} + +pub trait Format { + fn format(&mut self, f: T); +} + +impl Format for String { + fn format(&mut self, f: T) { + let mut res = String::new(); + let mut formatting = false; + for c in self.chars().into_iter() { + if c == '{' { + formatting = true; + res += &f.to_string(); + } else if c == '}' { + formatting = false; + } + if !formatting { + res.push(c); + } + } + self.clear(); + self.push_str(&res); + } +} diff --git a/src/libk/string/mod.rs b/src/libk/string/mod.rs new file mode 100644 index 0000000..db7b59d --- /dev/null +++ b/src/libk/string/mod.rs @@ -0,0 +1 @@ +pub mod format;