Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/target
**/*.rs.bk
/Cargo.lock
/Cargo.lock
.idea
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
```
4 changes: 4 additions & 0 deletions build.bat
Original file line number Diff line number Diff line change
@@ -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
2 changes: 2 additions & 0 deletions src/dos.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
59 changes: 59 additions & 0 deletions src/dos/env.rs
Original file line number Diff line number Diff line change
@@ -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
}
24 changes: 17 additions & 7 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,32 @@
#![feature(abi_x86_interrupt)]
#![no_std]
#![no_main]

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!");
}
}