forked from MightyPork/crsn
make it work with musl (the _nox target does not link the screen module that wouldn't build)
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
[package]
|
||||
name = "launcher_nox"
|
||||
version = "0.1.0"
|
||||
authors = ["Ondřej Hruška <ondra@ondrovo.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
crsn = { path = "../crsn" }
|
||||
crsn_arith = { path = "../crsn_arith" }
|
||||
crsn_buf = { path = "../crsn_buf" }
|
||||
crsn_stdio = { path = "../crsn_stdio" }
|
||||
|
||||
simple_logger = "1.9.0"
|
||||
log = "0.4.11"
|
||||
thiserror = "1.0.20"
|
||||
anyhow = "1.0.32"
|
||||
clappconfig = "0.4.0"
|
||||
|
||||
serde = { version = "1.0.116", features = ["derive"] }
|
||||
@@ -0,0 +1,172 @@
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use std::time::Duration;
|
||||
|
||||
use clappconfig::{AppConfig, clap};
|
||||
use clappconfig::clap::ArgMatches;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crsn::asm::data::literal::Addr;
|
||||
use crsn::module::{OpTrait, CrsnUniq};
|
||||
use crsn::runtime::run_thread::{RunThread, ThreadToken, ThreadParams};
|
||||
use crsn_arith::ArithOps;
|
||||
use crsn_stdio::StdioOps;
|
||||
use crsn_buf::BufOps;
|
||||
|
||||
mod read_file;
|
||||
mod serde_duration_millis;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
struct LogConfig {
|
||||
level: String,
|
||||
modules: HashMap<String, String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(default)]
|
||||
struct Config {
|
||||
log: LogConfig,
|
||||
#[serde(skip)]
|
||||
program_file: String,
|
||||
#[serde(skip)]
|
||||
assemble_only: bool,
|
||||
#[serde(with = "serde_duration_millis")]
|
||||
cycle_time: Duration,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
log: LogConfig {
|
||||
level: "warn".to_string(),
|
||||
modules: Default::default(),
|
||||
},
|
||||
program_file: "".to_string(),
|
||||
assemble_only: false,
|
||||
cycle_time: Duration::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AppConfig for Config {
|
||||
type Init = Self;
|
||||
|
||||
fn logging(&self) -> &str {
|
||||
&self.log.level
|
||||
}
|
||||
|
||||
fn logging_mod_levels(&self) -> Option<&HashMap<String, String>> {
|
||||
Some(&self.log.modules)
|
||||
}
|
||||
|
||||
fn pre_log_println(_message: String) {
|
||||
// shut up
|
||||
}
|
||||
|
||||
fn print_banner(_name: &str, _version: &str) {
|
||||
// No banner
|
||||
}
|
||||
|
||||
/// Add args to later use in the `configure` method.
|
||||
fn add_args<'a: 'b, 'b>(clap: clap::App<'a, 'b>) -> clap::App<'a, 'b> {
|
||||
// Default impl
|
||||
clap
|
||||
.arg(
|
||||
clap::Arg::with_name("input")
|
||||
.value_name("FILE")
|
||||
.help("Program to run")
|
||||
.required_unless("default-config")
|
||||
.takes_value(true),
|
||||
)
|
||||
.arg(
|
||||
clap::Arg::with_name("asm-only")
|
||||
.short("P")
|
||||
.long("asm")
|
||||
.help("Only assemble, do not run."),
|
||||
)
|
||||
.arg(
|
||||
clap::Arg::with_name("cycle")
|
||||
.long("cycle")
|
||||
.short("C")
|
||||
.value_name("MICROS")
|
||||
.help("Cycle time (us, append \"s\" or \"ms\" for coarser time)")
|
||||
.takes_value(true),
|
||||
)
|
||||
}
|
||||
|
||||
fn configure(mut self, clap: &ArgMatches) -> anyhow::Result<Self> {
|
||||
self.program_file = clap.value_of("input").unwrap().to_string();
|
||||
self.assemble_only = clap.is_present("asm-only");
|
||||
if let Some(t) = clap.value_of("cycle") {
|
||||
let (t, mul) = if t.ends_with("us") {
|
||||
(&t[..(t.len()-2)], 1)
|
||||
} else if t.ends_with("ms") {
|
||||
(&t[..(t.len()-2)], 1000)
|
||||
} else if t.ends_with("m") {
|
||||
(&t[..(t.len()-1)], 1000)
|
||||
} else if t.ends_with("u") {
|
||||
(&t[..(t.len()-1)], 1)
|
||||
} else if t.ends_with("s") {
|
||||
(&t[..(t.len()-1)], 1000_000)
|
||||
} else {
|
||||
(t, 1)
|
||||
};
|
||||
|
||||
self.cycle_time = Duration::from_micros(t.parse::<u64>().expect("parse -C value") * mul);
|
||||
println!("ct = {:?}", self.cycle_time);
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let config = Config::init("crsn", "crsn.json5", env!("CARGO_PKG_VERSION"))?;
|
||||
|
||||
debug!("Loading {}", config.program_file);
|
||||
|
||||
let source = read_file::read_file(&config.program_file)?;
|
||||
|
||||
let uniq = CrsnUniq::new();
|
||||
|
||||
let parsed = crsn::asm::assemble(&source, &uniq, vec![
|
||||
ArithOps::new(),
|
||||
BufOps::new(),
|
||||
StdioOps::new(),
|
||||
])?;
|
||||
|
||||
if config.assemble_only {
|
||||
for (n, op) in parsed.ops.iter().enumerate() {
|
||||
println!("{:04} : {}", n, op.to_sexp());
|
||||
}
|
||||
return Ok(());
|
||||
} else {
|
||||
trace!("--- Compiled program ---");
|
||||
for (n, op) in parsed.ops.iter().enumerate() {
|
||||
trace!("{:04} : {}", n, op.to_sexp());
|
||||
}
|
||||
trace!("------------------------");
|
||||
}
|
||||
|
||||
debug!("Start runtime");
|
||||
|
||||
let args = &[];
|
||||
let thread = RunThread::new(ThreadParams {
|
||||
id: ThreadToken(0),
|
||||
uniq,
|
||||
program: parsed,
|
||||
pc: Addr(0),
|
||||
cycle_time: config.cycle_time,
|
||||
args
|
||||
});
|
||||
|
||||
// run without spawning, so it is on the main thread - required by some extensions
|
||||
thread.run();
|
||||
|
||||
debug!("Runtime shut down.");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::io::Read;
|
||||
use std::path::Path;
|
||||
|
||||
/// Read a file to string
|
||||
pub fn read_file<P: AsRef<Path>>(path: P) -> io::Result<String> {
|
||||
let path = path.as_ref();
|
||||
let mut file = File::open(path)?;
|
||||
|
||||
let mut buf = String::new();
|
||||
file.read_to_string(&mut buf)?;
|
||||
Ok(buf)
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
use std::time::Duration;
|
||||
|
||||
use serde::{self, Deserialize, Deserializer, Serializer};
|
||||
|
||||
pub fn serialize<S>(value: &Duration, se: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
se.serialize_u64(value.as_secs() * 1000 + value.subsec_millis() as u64)
|
||||
}
|
||||
|
||||
pub fn deserialize<'de, D>(de: D) -> Result<Duration, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s: u64 = u64::deserialize(de)?;
|
||||
Ok(Duration::from_millis(s))
|
||||
}
|
||||
Reference in New Issue
Block a user