diff --git a/.gitignore b/.gitignore index 212181d..eb5eca4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /target **/*.rs.bk -/Cargo.lock \ No newline at end of file +/Cargo.lock +.idea \ No newline at end of file diff --git a/README.md b/README.md index 248266b..b1eccb6 100644 --- a/README.md +++ b/README.md @@ -90,3 +90,11 @@ dpkey module steals key input processing from DOS and converts scan code to asci about scan code: see [PS/2 Keyboard - OSDev Wiki](https://wiki.osdev.org/PS/2_Keyboard). ![sample2](https://github.com/o8vm/rust_dos/blob/images/dpkey.gif) + +## Tests + +To run the tests suite, you can type on your DOS emulator: + +```shell +rust_dos.com test +``` \ No newline at end of file diff --git a/build.bat b/build.bat new file mode 100644 index 0000000..c656438 --- /dev/null +++ b/build.bat @@ -0,0 +1,4 @@ +@echo off +set RUST_BACKTRACE=full +cargo build --release +cargo objcopy --release -- -O binary --binary-architecture=i386:x86 rust_dos.com \ No newline at end of file diff --git a/src/dos.rs b/src/dos.rs index 7f4635e..89dd9f7 100644 --- a/src/dos.rs +++ b/src/dos.rs @@ -9,6 +9,8 @@ pub mod error_code; pub mod panic; pub mod math; pub mod cooperative_multitasking; +pub mod env; + use core::arch::asm; pub use alloc::string::String as String; diff --git a/src/dos/env.rs b/src/dos/env.rs new file mode 100644 index 0000000..b7fb1b2 --- /dev/null +++ b/src/dos/env.rs @@ -0,0 +1,59 @@ +use alloc::vec::Vec; +use core::slice; + +fn command_tail<'a>() -> &'a [u8] { + let ptr = 0x80 as *const u8; + let (len, bytes) = unsafe { + let len = *ptr as usize; + (len, slice::from_raw_parts(ptr.add(1), len)) + }; + let trimmed = bytes.iter() + .position(|&b| b == 0x0D) + .unwrap_or(len); + &bytes[..trimmed] +} + +/// Returns the command line arguments as a vector of string slices. +/// Handles quoted arguments and whitespace separation. +/// +/// # Warning +/// Unlike standard operating system, the first argument (index 0) is not the program name, +/// but the first argument after the program name. +pub fn args() -> Vec<&'static str> { + let mut args = Vec::new(); + let line = command_tail(); + + let s = unsafe { core::str::from_utf8_unchecked(line) }; + let bytes = s.as_bytes(); + let len = bytes.len(); + let mut i = 0; + + while i < len { + while i < len && bytes[i].is_ascii_whitespace() { + i += 1; + } + if i >= len { break; } + + let start = i; + let mut in_quotes = false; + + while i < len { + let c = bytes[i]; + if c == b'"' { + in_quotes = !in_quotes; + i += 1; + continue; + } + if !in_quotes && c.is_ascii_whitespace() { + break; + } + i += 1; + } + + let end = i; + let token = s[start..end].trim_matches('"'); + args.push(token); + } + + args +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index a6344fb..a9116b5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +#![feature(abi_x86_interrupt)] #![no_std] #![no_main] @@ -5,18 +6,27 @@ extern crate alloc; mod dos_tests; -use rust_dos::*; use crate::dos_tests::allocator_test::allocator_test; +use crate::dos_tests::cooperative_multitasking_test::cooperative_multitasking_test; use crate::dos_tests::datetime::datetime_test; use crate::dos_tests::file::file_read_test; -use crate::dos_tests::cooperative_multitasking_test::cooperative_multitasking_test; +use rust_dos::*; entry!(main); fn main() { - allocator_test(); - file_read_test(); - datetime_test(); - cooperative_multitasking_test(); - println!("Hello, World!"); + let args = dos::env::args(); + + if args.len() >= 1 && args[0] == "test" { + allocator_test(); + file_read_test(); + datetime_test(); + cooperative_multitasking_test(); + } else { + println!("Hello, World!"); + } } + + + +